Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Представить файл в HEX-виде [D7, XP]


Страницы:   1 2 3

Cramol ©   (2011-05-28 22:59:00) 

Здравствуйте! Подскажите, пожалуйста, как сделать так, чтобы при нажатии на кнопку через OpenDialog1 выбранный файл оказался в массиве в шестнадцатеричном виде?
Это вот, знаете как, если открыть, к примеру, exe-файл в блокноте - там будут кракозябры. Вот мне надо так же, но только чтобы были не кракозябры, а именно HEX-последовательность: FF 01 A1 3F и т.д. Всё в один массив, весь файл.
Буду очень признателен за помощь!!


Anatoly Podgoretsky   (2011-06-01 14:04:00) [1]

> sniknik  (01.06.2011 12:39:35)  [35]

Переписать все нафиг.


clickmaker   (2011-06-01 13:08:00) [2]

> Насколько помню, обычный Edit имеет предел 64К. Или уже
> нет?

это только в win9x


Юрий Зотов   (2011-06-01 13:07:00) [3]

А задача, ИМХО, просто учебная. Так что особо заморачиваться вряд ли стоит.


Юрий Зотов   (2011-06-01 13:05:00) [4]


clickmaker ©   (01.06.11 12:15) [34]
> а зачем RichEdit для hex-вида? Обычный Edit гораздо шустрее

Насколько помню, обычный Edit имеет предел 64К. Или уже нет?


sniknik   (2011-06-01 12:55:00) [5]

> боюсь, тут нужен будет свой контрол для отображения.
по постановке [0] отображать тоже не нужно, просто -
> выбранный файл оказался в массиве в шестнадцатеричном виде?
а в каком виде оно будет если просто массив байт? в десятичном?

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


clickmaker   (2011-06-01 12:44:00) [6]

> а зачем вообще конвертировать все(?), если можно только
> отображаемую часть

боюсь, тут нужен будет свой контрол для отображения. Стандартные в виртуальном режиме не работают, как известно. Хотя, извратиться попробовать можно, но перехватывать всю навигацию по тексту - задача не такая тривиальная


sniknik   (2011-06-01 12:39:00) [7]

> а зачем RichEdit для hex-вида? Обычный Edit гораздо шустрее
а зачем вообще конвертировать все(?), если можно только отображаемую часть. просто автор дал такие "предпосылки"(код, который и правят, а надо логику менять, а логика она от задачи, про которую ни слова, зависит...).


clickmaker   (2011-06-01 12:15:00) [8]

а зачем RichEdit для hex-вида? Обычный Edit гораздо шустрее


Юрий Зотов   (2011-06-01 04:07:00) [9]

В такой редакции чистая скорость цикла - около 100 MB/sec

const
 H: array[0..15] of char =
   ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F');

procedure TForm1.FormShow(Sender: TObject);
var
 M: TMemoryStream;
 S: string;
 P: PByte;
 Q: PChar;
 i: integer;
 T: cardinal;
begin
 with TOpenDialog.Create(nil) do
 try
   if Execute then
   begin
     RichEdit1.Clear;
     M := TMemoryStream.Create;
     try
       M.LoadFromFile(FileName);
       SetLength(S, M.Size * 2);
       P := M.Memory;
       Q := @S[1];
       T := GetTickCount;
       for i := 1 to M.Size do
       begin
         Q^ := H[P^ shr 4];
         Inc(Q);
         Q^ := H[P^ and $0F];
         Inc(Q);
         Inc(P)
       end;
       T := GetTickCount - T;
       I := M.Size
     finally
       M.Free
     end;
     RichEdit1.Text := S;
     ShowMessage(FloatToStr(I / (1.024 * 1024 * T)) + ' MB/sec')
   end
 finally
   Free
 end
end;

А если измерять скорость с учетом заполнения RichEdit, то она оказывается ниже в 30-40 раз. Это означает, что дальнейшая оптимизация цикла практического смысла не имеет.


Юрий Зотов   (2011-06-01 03:24:00) [10]


> Sha ©   (01.06.11 02:04) [31]
> На моем компе чистая скорость работы цикла - 3,22 MB/sec

Да, я подозревал, что значительную часть времени тратит RichEdit, но проверять не стал.

Прочие доработки, которые ты сделал (прямой адрес приемника вместо индекса символа и использование таблицы вместо IntToHex) - это и есть то, что я хотел оставить автору.
:o)


Sha   (2011-06-01 02:04:00) [11]

> Юрий Зотов ©   (31.05.11 22:24) [28]
> У меня работает со скоростью около 1 MB/sec

На моем компе чистая скорость работы цикла - 3,22 MB/sec
Если в цикле оставить только инкремент адреса - 425 MB/sec
Если переписать цикл как ниже - 322 MB/sec
       for i := 1 to M.Size do
       begin
         Q^:=H[byte(p^)];
         inc(Q);
         Inc(P)
       end;

Если читать по 2 байта, писать по 4, используя ту же таблицу наверно будет еще быстрее.
Если при этом читать блоками или использовать MMF,
то на вычисления время вообще не потратится.


sniknik   (2011-06-01 00:29:00) [12]

> но выглядеть будет хорошо/быстро
именно выглядеть... т.к. общее время "загрузки" будет больше чем например в Юрий Зотов ©   (31.05.11 22:24) [28]


sniknik   (2011-06-01 00:24:00) [13]

тоже не оптимально, надо бы под тип DB аваре компонент, данные отдельно (через тот же FileMapping) отображение отдельно, тогда и потоки не нужны, и размер не важен (отображается только видимая, малая часть)

но выглядеть будет хорошо/быстро (пока не упрется в обычные ограничения визуального компонента используемого как хранилище данных... )

unit Unit1;

interface

uses
 Windows, Messages, SysUtils, StdCtrls, ComCtrls, Classes, Controls, Forms, Dialogs;

type
 TForm1 = class(TForm)
   Button1: TButton;
   RichEdit1: TRichEdit;
   procedure Button1Click(Sender: TObject);
 private
 public
 end;

var
 Form1: TForm1;

implementation

{$R *.dfm}

type
 TFillThread = class(TThread)
   Handle: THandle;
   FileName: string;
 protected
   procedure Execute; override;
 public
   constructor Create(Handle: THandle; const FileName: string);
 end;

constructor TFillThread.Create(Handle: THandle; const FileName: string);
begin
 inherited Create(true);
 self.Handle  := Handle;
 self.FileName:= FileName;
 FreeOnTerminate:= true;
 Resume;
end;

procedure TFillThread.Execute;
const
 MaxBuf = 1024;
 Hex: array[0..15] of Char = '0123456789ABCDEF';
var
 Data: file;
 i, NumRead: integer;
 Buf : array[0..MaxBuf - 1] of Char;
 Edit: array[0..MaxBuf * 2] of Char;
begin
 FileMode:= fmOpenRead;

 AssignFile(Data, FileName);
 Reset(Data, 1);
 repeat
   BlockRead(Data, Buf, MaxBuf, NumRead);

   for i:= 0 to NumRead-1 do begin
     Edit[i*2]  := Hex[Byte(Buf[i]) shr $4];
     Edit[i*2+1]:= Hex[Byte(Buf[i]) and $F];
   end;
   Edit[NumRead * 2]:= #0;

   SendMessage(Handle, EM_SETSEL, -1, 0);
   SendMessage(Handle, EM_REPLACESEL, 0, Lparam(@Edit));
 until (NumRead < MaxBuf);

 CloseFile(Data);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
 with TOpenDialog.Create(nil) do
   try
     if Execute then begin
       RichEdit1.Clear;
       TFillThread.Create(RichEdit1.Handle, FileName);
     end;
   finally
     Free;
   end;
end;

end.


Юрий Зотов   (2011-05-31 22:24:00) [14]

> Cramol   (29.05.11 12:10) [13]

Если больше 10 Мб загружать не надо, то сойдет вот это:

procedure TForm1.FormShow(Sender: TObject); // Обработчик OnShow
var
 M: TMemoryStream;
 S: string;
 P: PChar;
 i, j: integer;
 B: string[2];
 T : cardinal;
begin
 with TOpenDialog.Create(nil) do
 try
   if Execute then
   begin
     RichEdit1.Clear;
     T := GetTickCount;
     M := TMemoryStream.Create;
     try
       M.LoadFromFile(FileName);
       SetLength(S, M.Size * 2);
       P := M.Memory;
       for i := 1 to M.Size do
       begin
         j := i * 2;
         B := IntToHex(Byte(P^), 2);
         S[j - 1] := B[1];
         S[j] := B[2];
         Inc(P)
       end
     finally
       I := M.Size;
       M.Free
     end;
     RichEdit1.Text := S;
     T := GetTickCount - T;
     ShowMessage(FloatToStr(I / (1.024 * 1024 * T)) + ' MB/sec')
   end
 finally
   Free
 end
end;

У меня работает со скоростью около 1 MB/sec (то есть, 20-метровый файл грузит примерно за 20 сек). Только имейте в виду, что код далеко не оптимальный, поэтому разберитесь в нем и постарайтесь его улучшить.


Sha   (2011-05-31 22:16:00) [15]

Чтобы сделать слегка тормознутую надо читать файл в цикле по одному байту,
хотя можно читать блоками или вообще все за один раз.

А чтобы серьезно все замедлить надо в цикле сделать что-нибудь посерьезнее,
например, сохранить какую нибудь фигню в файл.

Не надо читать справку по используемым функциям,
не надо форматировать код,
не надо читать советы [20,23], как исправить ошибки,
пусть это сделает кто-нибудь другой и даст мне код.

--
Вредные советы.


Cramol   (2011-05-31 20:11:00) [16]

Видимо, нет :(


Cramol   (2011-05-30 12:45:00) [17]

Извиняюсь за бестактную наглость, но не поможете как это кодом правильно написать?


Anatoly Podgoretsky   (2011-05-30 09:41:00) [18]

> RWolf  (30.05.2011 09:38:23)  [23]

Ему на это уже указавали пальце, это страшно так работать со Strings


RWolf   (2011-05-30 09:38:00) [19]


> Anatoly Podgoretsky ©   (30.05.11 07:36) [22]

Ну так у автора виснет не потому, что он читает файл побайтно, а потому, что на каждое чтение байта из файла у него приходится одно сохранение картинки.
А проглядел он это потому, что игнорирует форматирование исходников.


Anatoly Podgoretsky   (2011-05-30 07:36:00) [20]

> VirEx  (30.05.2011 06:59:21)  [21]

Пользователя этим не испугаешь, он снесет приложение через диспетчер задач.


Страницы:   1 2 3

Наверх

Титульная страница Поиск, карта сайта Написать письмо