Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > [ "Начинающим" ]
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 19.08.2011, 08:03
royun royun вне форума
Прохожий
 
Регистрация: 19.08.2011
Сообщения: 28
Репутация: 10
По умолчанию Конвертер бинарных данных

Хочу написать конвертер бинарного файла, который переводит его на читабельный вид. Есть описание бинарного файла (структура) и сам файл. Не могу понять, как использовать описание этого файла при написании конвертера. С чего оттолкнуться, с чего начать подскажите пожалуйста
Ответить с цитированием
  #2  
Старый 19.08.2011, 08:38
Аватар для NumLock
NumLock NumLock вне форума
Let Me Show You
 
Регистрация: 30.04.2010
Адрес: Северодвинск
Сообщения: 5,426
Версия Delphi: 7, XE5
Репутация: 59586
По умолчанию

для начала можно сделать просмотр в HEX+ASCII-виде, как это делает, например, Total Commander: F3-Options-Hex. вполне читабельно
__________________
Пишу программы за еду.
__________________
Ответить с цитированием
  #3  
Старый 20.08.2011, 21:40
Аватар для Страдалецъ
Страдалецъ Страдалецъ вне форума
Гуру
 
Регистрация: 09.03.2009
Адрес: На курорте, из окна вижу теплое Баренцево море. Бррр.
Сообщения: 4,723
Репутация: 52347
По умолчанию

Цитата:
Сообщение от royun
Хочу написать конвертер бинарного файла, который переводит его на читабельный вид. Есть описание бинарного файла (структура) и сам файл. Не могу понять, как использовать описание этого файла при написании конвертера. С чего оттолкнуться, с чего начать подскажите пожалуйста
Как я понял вы не знакомы с функциями BlockRead, BlockWrite которые используются для чтения/записи бинарных данных. Можно конечно воспользоваться FileStream для этих целей, но мне кажется для вас это будет сложновато.
__________________
Жизнь такова какова она есть и больше никакова.
Помогаю за спасибо.
Ответить с цитированием
  #4  
Старый 21.08.2011, 08:55
Аватар для M.A.D.M.A.N.
M.A.D.M.A.N. M.A.D.M.A.N. вне форума
Sir Richard Abramson
 
Регистрация: 05.04.2008
Сообщения: 5,505
Версия Delphi: XE10
Репутация: выкл
По умолчанию

Есть готовый компон, который тебе представляет файл в стиле WinHEX.
MSHexEdit.
__________________
— Как тебя понимать?
— Понимать меня не обязательно. Обязательно меня любить и кормить вовремя.


На Delphi, увы, больше не программирую.
Рекомендуемая литература по программированию
Ответить с цитированием
  #5  
Старый 21.08.2011, 11:13
chainik chainik вне форума
Начинающий
 
Регистрация: 30.06.2008
Сообщения: 140
Репутация: 8882
По умолчанию

задача как-то неясно поставлена.
Начать можно например с чтения файла в структуру
Например так

Код:
type
TMyStruct=record
                <здесь описание структуры>
                end; 

var
z:TMyStruct;    //сюда копируется файл

procedure ReadMyStruct(fnam:string);
var
F:file of TMyStruct;
begin
assignfile(F,Fnam);reset(F);
read(F,z);
CloseFile(F);
end;

а еще рекомендую почитать описание функций BlockRead, BlockWrite,
работа с типированными и нетипированными файлами.
Ответить с цитированием
  #6  
Старый 21.08.2011, 11:21
Аватар для M.A.D.M.A.N.
M.A.D.M.A.N. M.A.D.M.A.N. вне форума
Sir Richard Abramson
 
Регистрация: 05.04.2008
Сообщения: 5,505
Версия Delphi: XE10
Репутация: выкл
По умолчанию

Цитата:
Сообщение от chainik
задача как-то неясно поставлена.
Начать можно например с чтения файла в структуру
Например так

Код:
type
TMyStruct=record
                <здесь описание структуры>
                end; 

var
z:TMyStruct;    //сюда копируется файл

procedure ReadMyStruct(fnam:string);
var
F:file of TMyStruct;
begin
assignfile(F,Fnam);reset(F);
read(F,z);
CloseFile(F);
end;

а еще рекомендую почитать описание функций BlockRead, BlockWrite,
работа с типированными и нетипированными файлами.

Берем книгу Льва Толстого и ставим в холодильник.

Зачем читать файл в некую структуру? Файл произвольных двоичных данных.
Вообще достаточно вычитывать по 16 байт за проход цикла, в array of byte к примеру, после чего в конечный файл записывать эти данные, обработав ф-ей IntToHex.
__________________
— Как тебя понимать?
— Понимать меня не обязательно. Обязательно меня любить и кормить вовремя.


На Delphi, увы, больше не программирую.
Рекомендуемая литература по программированию
Ответить с цитированием
  #7  
Старый 22.08.2011, 01:20
Аватар для Страдалецъ
Страдалецъ Страдалецъ вне форума
Гуру
 
Регистрация: 09.03.2009
Адрес: На курорте, из окна вижу теплое Баренцево море. Бррр.
Сообщения: 4,723
Репутация: 52347
По умолчанию

M.A.D.M.A.N.
Да с чего ты взял что нужно HEX-представление? Есть просто файл и есть описание, сколько байт прочитать для одной переменно сколько для другой и т.д. BlockRead и все.
__________________
Жизнь такова какова она есть и больше никакова.
Помогаю за спасибо.
Ответить с цитированием
  #8  
Старый 22.08.2011, 08:55
royun royun вне форума
Прохожий
 
Регистрация: 19.08.2011
Сообщения: 28
Репутация: 10
По умолчанию

И так есть бинарный файл, я написал программку, которая считывает ее. А также есть описание структуры файла, не могу понять как использовать ее, в смысле как написать эту структуру программно. Я так понял описание структуры файла используется чтобы мы правильно прочитали этот файл. Вот вложил описание этого файла.
Вложения
Тип файла: rar A4.rar (35.3 Кбайт, 23 просмотров)
Ответить с цитированием
  #9  
Старый 22.08.2011, 14:34
Аватар для Страдалецъ
Страдалецъ Страдалецъ вне форума
Гуру
 
Регистрация: 09.03.2009
Адрес: На курорте, из окна вижу теплое Баренцево море. Бррр.
Сообщения: 4,723
Репутация: 52347
По умолчанию

Итак пойдем плясать от печки:
1. У вас возможны 3 вида файла: IA.ICAMA, IA.ICIAR, IA.ICINA
Последние 5 букв видимо расширение по которому вы будете определять тип данных в конкретном файле.
Для первого типа файла имеем такое описание:
Цитата:
 Длина блока: 8192 байт;
 Длина записи : 8192 байт;
 Формат записи : фиксированный (F).
Значит BlockRead нам не очень подходит для чтения. Самый простой описатель для чтения будет таким:
Код:
Type 
ICAMA = record
 Data: Array[1..8192] of byte;
end;

И код для чтения данных записями будет такой:
Код:
Type 
ICAMA = record
 Data: Array[1..8192] of byte;
end;

Var
 F: File of ICAMA;
 R: ICAMA;
begin
 AssignFile(F, 'c:\IA.ICAMA');
 Reset(F);
 while not Eof(F) do Read(F, R);
 CloseFile(F);
end.
Данный код ничего не возвращает, но он честно читает ваш файл.
А вот что касается чтения содержимого каждой из записи - это уже скорее всего в работу.
__________________
Жизнь такова какова она есть и больше никакова.
Помогаю за спасибо.

Последний раз редактировалось Страдалецъ, 22.08.2011 в 14:39.
Ответить с цитированием
  #10  
Старый 22.08.2011, 18:25
OnzMill OnzMill вне форума
Прохожий
 
Регистрация: 06.10.2009
Сообщения: 48
Репутация: 10
По умолчанию

А почему нельзя загнать файл в поток и работать с потоками?
Остальное все описано в том документе. Сложного там я не вижу ничего. Смотри пунт 5.
__________________
Говори что думаешь, думай, что говоришь.
(Шоссе 60)

Последний раз редактировалось OnzMill, 22.08.2011 в 19:01.
Ответить с цитированием
  #11  
Старый 22.08.2011, 19:47
Аватар для Страдалецъ
Страдалецъ Страдалецъ вне форума
Гуру
 
Регистрация: 09.03.2009
Адрес: На курорте, из окна вижу теплое Баренцево море. Бррр.
Сообщения: 4,723
Репутация: 52347
По умолчанию

Можно и в поток, но не думаю, что автору темы будет легче от этого.
__________________
Жизнь такова какова она есть и больше никакова.
Помогаю за спасибо.
Ответить с цитированием
  #12  
Старый 23.08.2011, 05:53
royun royun вне форума
Прохожий
 
Регистрация: 19.08.2011
Сообщения: 28
Репутация: 10
По умолчанию

Вот дан ПРИМЕР. ПАКЕТ 101: НОМЕР АБОНЕНТА Б
ПРИМЕР: 078912345 (набираемые цифры)

№--|Байтовая|Длина|------Hазвание поля-----------|Битовая позиция |
поля|позиция |_____|_7|_6|_5_|_4_|_3_|_2_|_1_|_0|7_6_5_4_3_2_1_ 0_|
_1__|__1_____|_1___|______НОМЕР ПАКЕТА________|_____6__|__5____ |
_2__|__2_____|_12__|_РЕЗ|_ДЛИНА № АБОНЕТА Б___|_____0__|__9____ |
_3__|__3_____|----------№ АБОНЕНТА Б-------------|------0--|--7-----|
-----|__4_____|-------------------------------------|------8--|---9-----|
-----|__5_____|-------------------------------------|------1--|---2-----|
-----|__6_____|-------------------------------------|------3--|---4-----|
-----|__7_____|_________________________________|_____5 __|_______|

Уважаемые форумчане вот смотрю на этот пример и ничего не пойму. Подскажите пожалуйста непонятливому как описать этот пример программно.
Ответить с цитированием
  #13  
Старый 27.08.2011, 10:56
chainik chainik вне форума
Начинающий
 
Регистрация: 30.06.2008
Сообщения: 140
Репутация: 8882
По умолчанию

у меня получилось примерно это
Функции не тестировал, заранее приношу извинения за ошибки.
короче, разбираться со всем этим надо долго и тоскливо.
особенно угнетает переменная длина, из-за чего надо использовать динамич массивы. При чтении файла не забудь команду выделения под него памяти SetLength(NumAbon, <длина номера абонента>)

Возможно лучшим решением было бы использовать потоки.

Код:
type

TP101=record
     Packet:byte;    // номер пакета=101
     Dlina:byte;     // рез + длина номера
     NumAbon:array of byte;  // номер абонента
     end;



var
P101:Tp101;

function GetRes():integer;
begin
Result:=P101.Dlina shr 6;
end;

function GetDlinaNum():integer;
begin
Result:=P101.Dlina and $3F;
end;

{---------------------------------------------------------
    переводит упакованный массив байт
    номера абонента в строку
на Ассемблере было бы изящнее. 
Но учитывая малую длину поля-можно и так.
------------------------------------------------------------}
function UnPack(var NN:array of byte):string;
var
p:^byte;
begin
Result:='';
p:=@NN[0];         //уст указатель на 1 байт -1
dec(p,1);
    repeat
    inc(p);
    Result:=Result + char(p^ shr 4 + ord('0')) + char((p^ and $FF + ord('0')));
    until p=@NN[High(NN)];
end;
Ответить с цитированием
  #14  
Старый 30.08.2011, 07:49
royun royun вне форума
Прохожий
 
Регистрация: 19.08.2011
Сообщения: 28
Репутация: 10
По умолчанию

Вот что получилось.

Код:
type
  AMA = packed record
  RecId : Byte;  //Идентификатор записи
  LenRec : Word; //Длина записи
  Flags : array[1..3] of Byte; //Флажки
  SeqAndStat : Byte; //Посл-сть записи Статус оплаты
  LenLacAndOwnId : Byte; //Длина LAC и ID владельца
  {DnA : TStream; - Проблема в том что не умею работать с потоками: как использовать поток затем вывести данные}
  DnA : array[1..5] of Byte; //Переменная часть - Номер абонента А - значение массива просто подобрал
                                     //исп. hexviewer
                             //Если просто пишу DnA : array of Byte; то выходит ошибка, где говорится о том
                             //что требуется финализация переменной  f: file of AMA;
                             //Значение переменного массива рассчитывается как DnA : array[1..i] of Byte
                             //где i = div [(LenLacAndOwnId+1)/2]
  //Описание Пакета № 100
  Np100 : Byte; //Номер пакета
  Date : array[1..3] of Byte; //Дата
  Time : array[1..3] of Byte; //Время
  Flags100 : Byte; //Флажки Пакета № 100
  Prod : array[1..3] of byte;//Прод-сть
  //Описание Пакета № 101
  Np101 : Byte; //Номер пакета
  LenDnB : Byte; //Длина номера абонента Б
  {DnB : TStream; - Проблема в том что не умею работать с потоками: как использовать поток затем вывести данные}
  DnB : array[1..1] of Byte;  //Переменная часть - Номер абонента Б - значение массива просто
                                      // подобрал исп. hexviewer
                              //Если просто пишу DnA : array of Byte; то выходит ошибка, где говорится о том
                             //что требуется финализация переменной  f: file of AMA;
                             //Значение переменного массива рассчитывается как DnB : array[1..j] of Byte
                             //где j = div [(LenDnB+1)/2]
  //Описание Пакета № 130
  Np130 : Byte; //Номер пакета
  LenP : Byte; //Длина пакета
  Zp : Word; //Значение причины
  RezAndOpr : byte; //Резерв и определение
  //Описание Пакета № 103
  Np103 : Byte; //Номер пакета
  TeTv : array[1..3] of byte; // Тарифные единицы для тарификации вызова
 
  end;
    TForm1 = class(TForm)
    Memo1: TMemo;
    Button1: TButton;
    OpenDialog: TOpenDialog;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
 
var
  Form1: TForm1;
 
implementation
 
{$R *.dfm}
 
procedure TForm1.Button1Click(Sender: TObject);
var
  f: file of AMA;
  open : Topendialog;
  Rec : AMA;
  Buffer : array [0..8191] of byte;
  NumRecsRead,t : integer;
begin
  memo1.Clear;
  open := TOpenDialog.Create(self);
  open.InitialDir := 'C:\000';
  open.Options := [ofFileMustExist];
  open.Filter :=  'ama files|*.*';
  open.Execute;
  AssignFile(f,open.FileName);
  {$I-}
  Reset(f);
  {$I+}
  seek(f,0);
  {while not eof(f) do
  begin}
  Read(f,Rec);
  memo1.Lines.Add(inttostr(Rec.RecId) + ' - ИДЕНТИФИКАТОР ЗАПИСИ');
  memo1.Lines.Add(inttostr(Rec.LenRec) + ' - ДЛИНА ЗАПИСИ');
  memo1.Lines.Add(inttostr(Rec.Flags[1]) + ' - Флажок F12');
  memo1.Lines.Add(inttostr(Rec.Flags[2]) + ' - Флажок F12');
  memo1.Lines.Add(inttostr(Rec.Flags[3]) + ' - Флажок F12');
  memo1.Lines.Add(inttostr(Rec.SeqAndStat) + ' - Посл-сть записи и статус оплаты');
  memo1.Lines.Add(inttostr(Rec.LenLacAndOwnId) + ' - Длина LAC и ID владельца');
  memo1.Lines.Add(inttohex(Rec.DnA[1],1) + inttohex(Rec.DnA[2],1) + inttohex(Rec.DnA[3],1) + inttohex(Rec.DnA[4],1) + inttohex(Rec.DnA[5],1) + ' - Номер абонента А');
  //Выводим пакет № 100
  memo1.Lines.Add(inttostr(Rec.Np100) + ' - Номер пакета');
  memo1.Lines.Add(inttohex(Rec.Date[3],1) +'.'+ inttohex(Rec.Date[2],1) +'.'+ inttohex(Rec.Date[1],1) + ' - Дата');
  memo1.Lines.Add(inttostr(Rec.Time[1]) +':'+ inttostr(Rec.Time[2]) +':'+ inttostr(Rec.Time[3]) + ' - Время');
  memo1.Lines.Add(inttohex(Rec.Prod[3],1) +':'+ inttohex(Rec.Prod[2],1) +':'+ inttohex(Rec.Prod[1],1) + ' - Продолжительность');
  //Выводим пакет № 101
  memo1.Lines.Add(inttostr(Rec.Np101) + ' - Номер пакета');
  memo1.Lines.Add(inttostr(Rec.LenDnB) + ' - Длина номера абонента Б');
  memo1.Lines.Add(inttostr(Rec.DnB[1]) + ' - Номера абонента Б');
  //Выводим пакет № 130
  memo1.Lines.Add(inttostr(Rec.Np130) + ' - Номер пакета');
  memo1.Lines.Add(inttostr(Rec.LenP) + ' - Длина пакета');
  memo1.Lines.Add(inttostr(Rec.Zp) + ' - Причина');
  memo1.Lines.Add(inttostr(Rec.RezAndOpr) + ' - Резерв и определение');  
 
  {end;}
  CloseFile(f);
  end;]

Как обойти ошибку которая требует финализации переменной f: file of AMA или дайте ссылочку где можно почитать про работу с потоками.

Последний раз редактировалось royun, 30.08.2011 в 09:02.
Ответить с цитированием
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 19:22.


 

Сайт

Форум

FAQ

Соглашения

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2025