![]() |
|
|
|||||||
| Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
![]() |
|
|
Опции темы | Поиск в этой теме | Опции просмотра |
|
#1
|
|||
|
|||
|
Хочу написать конвертер бинарного файла, который переводит его на читабельный вид. Есть описание бинарного файла (структура) и сам файл. Не могу понять, как использовать описание этого файла при написании конвертера. С чего оттолкнуться, с чего начать подскажите пожалуйста
|
|
#2
|
||||
|
||||
|
для начала можно сделать просмотр в HEX+ASCII-виде, как это делает, например, Total Commander: F3-Options-Hex. вполне читабельно
![]() |
|
#3
|
||||
|
||||
|
Цитата:
|
|
#4
|
||||
|
||||
|
Есть готовый компон, который тебе представляет файл в стиле WinHEX.
MSHexEdit. |
|
#5
|
|||
|
|||
|
задача как-то неясно поставлена.
Начать можно например с чтения файла в структуру Например так Код:
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
|
||||
|
||||
|
Цитата:
Берем книгу Льва Толстого и ставим в холодильник. Зачем читать файл в некую структуру? Файл произвольных двоичных данных. Вообще достаточно вычитывать по 16 байт за проход цикла, в array of byte к примеру, после чего в конечный файл записывать эти данные, обработав ф-ей IntToHex. |
|
#7
|
||||
|
||||
|
M.A.D.M.A.N.
Да с чего ты взял что нужно HEX-представление? Есть просто файл и есть описание, сколько байт прочитать для одной переменно сколько для другой и т.д. BlockRead и все. |
|
#8
|
|||
|
|||
|
И так есть бинарный файл, я написал программку, которая считывает ее. А также есть описание структуры файла, не могу понять как использовать ее, в смысле как написать эту структуру программно. Я так понял описание структуры файла используется чтобы мы правильно прочитали этот файл. Вот вложил описание этого файла.
|
|
#9
|
||||
|
||||
|
Итак пойдем плясать от печки:
1. У вас возможны 3 вида файла: IA.ICAMA, IA.ICIAR, IA.ICINA Последние 5 букв видимо расширение по которому вы будете определять тип данных в конкретном файле. Для первого типа файла имеем такое описание: Цитата:
Код:
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
|
|||
|
|||
|
А почему нельзя загнать файл в поток и работать с потоками?
Остальное все описано в том документе. Сложного там я не вижу ничего. Смотри пунт 5. Последний раз редактировалось OnzMill, 22.08.2011 в 19:01. |
|
#11
|
||||
|
||||
|
Можно и в поток, но не думаю, что автору темы будет легче от этого.
|
|
#12
|
|||
|
|||
|
Вот дан ПРИМЕР. ПАКЕТ 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
|
|||
|
|||
|
у меня получилось примерно это
Функции не тестировал, заранее приношу извинения за ошибки. короче, разбираться со всем этим надо долго и тоскливо. особенно угнетает переменная длина, из-за чего надо использовать динамич массивы. При чтении файла не забудь команду выделения под него памяти 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
|
|||
|
|||
|
Вот что получилось.
Код:
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. |