![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Представить файл в HEX-виде [D7, XP]
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]
Пользователя этим не испугаешь, он снесет приложение через диспетчер задач.