Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Для новичков > Чтение HEX из бинарника


Автор: Somebody32 1.4.2007, 17:51
Данная тема является дополнительной к http://forum.vingrad.ru/topic-137668/kw-%D0%B1%D0%B8%D0%BD%D0%B0%D1%80%D0%BD%D0%BE-hex-%D0%B7%D0%B0%D0%BF%D0%B8%D1%81%D1%8C/hl/hex%2Cand%2C%25D0%25B1%25D0%25B8%25D0%25BD%25D0%25B0%25D1%2580%25D0%25BD%25D0%25B8%25D0%25BA/index.html
Теперь вопрос в следующем, как считать данные, что находятся в файле перед записью. Т.е. мне требуется создать их бекап.

Пишу так:
Код

cg_file:=TFileStream.Create(OpenDialog1.FileName,fmOpenReadWrite);
cg_file.Position := StrToInt('$'+data.opt);
write_data := StrToInt('$'+temp_string);
cg_file.Write(write_data, SizeOf(write_data)); 


Соответственно проблема в следующем:
если запустить программу, осуществить запись, а потом строку:
Код

cg_file.Write(write_data, SizeOf(write_data)); 

на
Код

cg_file.Read(temp, SizeOf(write_data)); 


то в temp будет совсем не то, что я писал в тот раз. 

Прошу помощи, как я понял, ошибка мелочная, но никак поймать ее не могу.

Автор: MetalFan 1.4.2007, 18:27
ничо не понял. давай неработающий код.
а то когда ты там чего заменяешь - непонятно

Автор: Somebody32 1.4.2007, 18:36
Собственно он выше.
Объясняю. Есть файл, в который по офсетам надо записать данные, запись идет прекрасно, все работает. Но появилась потребность бекапить данные перед записью, т.е сначала пробежаться по адресам, считать все, что там было, а потом уже писать.
Так вот, допустим по адресу 003F13E3 я записал 2A002A002A.
Пытаюсь считать:
Код

cg_file:=TFileStream.Create(OpenDialog1.FileName,fmOpenReadWrite);
cg_file.Position := StrToInt('$'+data.opt);
write_data := StrToInt('$'+temp_string);
cg_file.Read(temp, SizeOf(write_data));
ShowMessage(inttostr(temp));

И он мне выдает последовательность цифр совсем не похожую на 2A002A002A.

Автор: Yanis 1.4.2007, 19:18
Сдаётся мне, что путаница у тебя возникает из-за того, что в HEX виде твои данные «смотрятся» наоборот.

Добавлено через 31 секунду
Выложи полный код. С типа переменных!

Автор: Somebody32 1.4.2007, 19:28
Код

procedure TForm1.Button3Click(Sender: TObject);
  var
  cg_file: TFileStream;
  patch_file: TextFile;
  patch_data_string, temp_string : String;
  data : TPatchOption;
  write_data,write_time,extra_symb,i,temp : integer;

begin
  if not TestUndoData then
    ShowMessage('Файл патча не содержит информации для восстановления. Она будет сгенерирована автоматически.');
  cg_file:=TFileStream.Create(OpenDialog1.FileName,fmOpenReadWrite);
  AssignFile(patch_file,OpenDialog2.FileName);
  Reset(patch_file);

    while(not eof(patch_file)) do
   begin
    Readln(patch_file,patch_data_string);
    data := GetOpt(patch_data_string,':');
    //ShowMessage(data.opt+' '+data.value);
    cg_file.Position := StrToInt('$'+data.opt);
    if length(data.value) >8 then
      begin
        write_time:=ceil(length(data.value)/8)-2;
        extra_symb:=length(data.value)-write_time*8;
        for i := 0 to write_time do
          begin
            temp_string := copy(data.value,i*8,8);
            //ShowMessage(temp_string+'!');
            write_data := StrToInt('$'+temp_string);
            //cg_file.Write(write_data, SizeOf(write_data));
            cg_file.ReadBuffer(temp,SizeOf(write_data));
            ShowMessage(inttostr(temp));
          end;
        temp_string := copy(data.value,(write_time+1)*8+1,extra_symb);
        ShowMessage(temp_string);
       // write_data := StrToInt('$'+temp_string);
        //cg_file.Write(write_data, SizeOf(write_data));
      end
    else
      begin
        write_data := StrToInt('$'+data.value);
        cg_file.Write(write_data, SizeOf(write_data));
      end;
   end;
   ShowMessage('Патч применен успешно!');
  closefile(patch_file);
  cg_file.Free;
end;

Автор: tht 2.4.2007, 01:22
а ты не мог бы показать строку HEX данные который ты записываешь и те данный которые тебе удается прочитать ? я бы тогда точно понял что у тебя за проблема.

Автор: MetalFan 2.4.2007, 08:26
Somebody32, и на основе каких данных ты делаешь вывод о " неправильной" записи?
делаешь Write, потом сразу Read и не то получаешь? ну так правильно тогда все...

Автор: Somebody32 2.4.2007, 19:32
MetalFan, естественно я прогу перезапускаю.

tht, пишу  по офсету 003F13E3 данные 2A002A002A, а получаю: 704653824

Автор: Yanis 2.4.2007, 19:35
Если переведёшь 704653824, то кое что заметишь. Значит ты где то глючишь smile

Добавлено через 2 минуты и 57 секунд
Что то меня смущает отсутсвие seek в коде smile

Автор: Somebody32 2.4.2007, 19:38
WinHex'ом  перевел это в HEX, оказалось то, что надо, как теперь только программно это в хекс перегнать?

Автор: Yanis 2.4.2007, 19:40
Ответ подкупающий своей неожаднностью -- с помощью IntToHex.

Автор: Somebody32 2.4.2007, 19:40
Yanis
Код

cg_file.Position := StrToInt('$'+data.opt);


это его аналог

Добавлено через 5 минут и 7 секунд
Yanis, да, что-то совсем косячить стал, спасибо, работает.

Автор: Yanis 2.4.2007, 19:50
Цитата(Somebody32 @  2.4.2007,  20:40 Найти цитируемый пост)
это его аналог

Я бы сказал, что это его противоположность smile

Цитата(Somebody32 @  2.4.2007,  20:40 Найти цитируемый пост)
спасибо, работает. 

smile

Автор: Somebody32 2.4.2007, 19:50
еще вопрос появился, 
если пишу это: 00002A002A002A002A, то, как видно из кода выше - пишу макс по 8 символов, иначе Strtoint выпадает с ошибкой, то, при чтении - нули урезаются, т.е мне выдается 2A002A002A02A. что с этим делать?

Автор: Yanis 2.4.2007, 19:52
Потому что 8 символов в HEX, это 4 байта. А 4 байта это максимальная размерность целого числа. Так что делай выводы.
Зачем тебе вообще числа? Используй обычные буферы типа массива символов.

Автор: Somebody32 2.4.2007, 19:55
Yanis, пример можно, и что делать с нулями, я так и не знаю...

Автор: Yanis 2.4.2007, 20:00
Попробуй сам поискать по форуму фразу TFileStream. Примеров до кучи. Сейчас нарисовать пример не могу.

Добавлено через 10 минут и 51 секунду
http://forum.vingrad.ru/index.php?showtopic=109545
http://forum.vingrad.ru/index.php?showtopic=107911
http://forum.vingrad.ru/index.php?showtopic=105640
как то так...

Автор: Somebody32 2.4.2007, 21:52
Почитал, но не нашел решения проблемы. Сейчас - все идеально, кроме одного:
при записи 
00002A002A002A002A читается все, кроме некоторых нулей! Как это обойти, я так и не понял =(

Автор: Yanis 2.4.2007, 22:07
Цитата(Somebody32 @  2.4.2007,  22:52 Найти цитируемый пост)
Как это обойти, я так и не понял =( 

Читать это в буфер типа Char или Byte. Не используй Integer или Word/DWORD.

Маленький пример:
Код
var
  f: TFileStream;
  buf, buf2: array[0..13] of Char;
begin
  buf := #$00#$2a#$00#$ab#$f0#$00#$00#$fe#$0e#$ab#$ce#$00#$00#$af;
  f := TFileStream.Create('c:\test.bin', fmCreate);
  f.WriteBuffer(buf, SizeOf(buf));
  f.Seek(0, soFromBeginning);
  f.ReadBuffer(buf2, SizeOf(buf2));
  ShowMessage(buf2);
  f.Free;
end;


Может я чего недопонял... Утро вечера мудреннее ;)

Автор: Somebody32 3.4.2007, 18:43
Хмм, ну,если следовать твоему совету/коду, то, после записи открываем хекс редактором и видим, что записано совсем не то...

Автор: Yanis 3.4.2007, 19:23
Прошу прощения за косяк. Уже исправил.

Автор: Somebody32 3.4.2007, 19:33
Теперь все пишется, но ничего не читается... Пустой бокс выдает.

Автор: Yanis 3.4.2007, 19:38
Цитата(Somebody32 @  3.4.2007,  20:33 Найти цитируемый пост)
Теперь все пишется, но ничего не читается... Пустой бокс выдает.

Господи, ну читается, но только там первым стоит символ #0, Delphi считает что строка на нём заканчивается.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)