Форум: "Начинающим";
Текущий архив: 2011.09.18;
Скачать: [xml.tar.bz2];
ВнизПредставить файл в HEX-виде Найти похожие ветки
← →
Cramol (2011-05-28 22:59) [0]Здравствуйте! Подскажите, пожалуйста, как сделать так, чтобы при нажатии на кнопку через OpenDialog1 выбранный файл оказался в массиве в шестнадцатеричном виде?
Это вот, знаете как, если открыть, к примеру, exe-файл в блокноте - там будут кракозябры. Вот мне надо так же, но только чтобы были не кракозябры, а именно HEX-последовательность: FF 01 A1 3F и т.д. Всё в один массив, весь файл.
Буду очень признателен за помощь!!
← →
Amoeba_ (2011-05-28 23:10) [1]
> ак сделать так, чтобы при нажатии на кнопку через OpenDialog1
Точно также, как и без нажатия на такую кнопку или даже при отсутствии OpenDialog1
А если серьезно, то изучаем ф-ию IntToHex и подключаем brain.sys
← →
Cramol (2011-05-29 00:54) [2]Дошел только до того, что перебираю посимвольно файл из memo, но при этом не получается сразу преобразовать символ в HEX и записать в другой memo :(
IntToStr(ord(s)); - тут хочу получить ascii-код string-символа, чтобы потом преобразовать в HEX используя IntToHex. Но выходит несовместимость типов(
ascii-код удается получить, если переменная s имеет тип ansichar, при этом просто с char он также не совместим(
Помогите, пожалуйста!
← →
RWolf © (2011-05-29 01:55) [3]не надо читать файлы через мемо, для этого есть специально предназначенные инструменты.
на выбор: file of byte, file, TFileStream.
← →
Sha © (2011-05-29 02:09) [4]> IntToStr(ord(s)); - тут хочу получить ascii-код string-символа,
A при помощи Ord() ты что получаешь?
← →
Cramol (2011-05-29 02:53) [5]>A при помощи Ord() ты что получаешь?
Числовой эквивалент символа
← →
Германн © (2011-05-29 03:06) [6]
> Числовой эквивалент символа
Вот его и пихай в IntToHex.
← →
clickmaker © (2011-05-29 03:13) [7]> Числовой эквивалент символа
хранится в парижской палате мер и весов
← →
Плохиш © (2011-05-29 03:38) [8]
> ascii-код удается получить, если переменная s имеет тип
> ansichar, при этом просто с char он также не совместим(
врать не надо, в указанной D7 char и ansichar один и тот же тип.
← →
Германн © (2011-05-29 05:16) [9]
> врать не надо
Он не врет. Он уже бредит. (Имхо сдача на носу). Поэтому сам не соображает, чего пишет. Что в коде, что на форуме.
> Но выходит несовместимость типов(
> ascii-код удается получить, если переменная s имеет тип
> ansichar, при этом просто с char он также не совместим(
>
В этой фразе сплошные смысловые "нестыковки".
Но он хоть не просит готовый код. Пока. :)
← →
Плохиш © (2011-05-29 10:12) [10]
> Cramol (29.05.11 02:53) [5]
> >A при помощи Ord() ты что получаешь?
> Числовой эквивалент символа
Справку почитать не пробовал, вместо своих домыслов?
← →
Cramol (2011-05-29 12:07) [11]С горем пополам как-то все же получилось :)
procedure TForm1.btn1Click(Sender: TObject);
var
Stream: TFileStream;
buf:byte;
i:longint;
begin
if Not dlgOpen1.Execute then Exit;
Stream:=TFileStream.Create(dlgOpen1.FileName, fmOpenRead);
Stream.Seek(0,soFromBeginning);
i:=0;
while i<Stream.Size do
begin
Stream.Read(buf,SizeOf(buf));
redt1.Text:= redt1.Text+IntToHex(buf, 2);
inc(i);
end;
end;
Файл интерпретируется в RichEdit сразу в HEX-виде. Вот только появилась другая проблема. Если файл весит, скажем, 1 Кб - всё нормально. Если 10 Кб - загружается секунд 15. Про 5-7 Мб вообще молчу.
Это можно как-то оптимизировать, чтобы скорость была побыстрее?
← →
Inovet © (2011-05-29 12:09) [12]> [11] Cramol (29.05.11 12:07)
> Про 5-7 Мб вообще молчу.
А если 100 ГБ как загружать будешь?
← →
Cramol (2011-05-29 12:10) [13]>А если 100 ГБ как загружать будешь?
Да не, мне больше 10 Мб не придется загружать
← →
Anatoly Podgoretsky © (2011-05-29 13:36) [14]
> Cramol (29.05.11 12:07) [11]
Это страшно загрузать по байту и особо страшно это работа с RichEdit - так память быстро кончится, там уже не до скорости будет.
← →
Sha © (2011-05-29 13:43) [15]> Cramol (29.05.11 12:07) [11]
> Это можно как-то оптимизировать, чтобы скорость была побыстрее?
Для этого надо:
или уменьшить количество действий,
или ускорить каждое действие,
или и то и другое.
--
Кэп.
← →
Cramol (2011-05-29 13:49) [16]>Это страшно загрузать по байту и особо страшно это работа с RichEdit - так память быстро кончится, там уже не до скорости будет.
Т.е. лучше будет загружать в память и там, непосредственно, уже работать с данными?
И скажите еще, пожалуйста...Вы говорите по байту страшно загружать. А как тогда лучше весь загружаемый файл преобразовать в HEX-вид?
← →
Inovet © (2011-05-29 13:54) [17]> [16] Cramol (29.05.11 13:49)
> А как тогда лучше весь загружаемый файл преобразовать в HEX-вид?
Лучше бы хранить в нормальном виде, а показывать кусок в каком хочешь. Ещё лучше и хранить кусок.
← →
clickmaker © (2011-05-29 14:15) [18]> Вы говорите по байту страшно загружать. А как тогда лучше
> весь загружаемый файл преобразовать в HEX-вид?
CreateFileMapping
← →
Cramol (2011-05-30 00:21) [19]Фух, вроде, получилось. Все работает, но проблема в том, что, опять же, если загружаемый файл по размеру от 100 Кб и больше - виснет :(
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, math, ComCtrls;
type
TForm1 = class(TForm)
OpenDialog1: TOpenDialog;
Image1: TImage;
Button4: TButton;
redt1: TRichEdit;
procedure Button4Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
function StreamToHex(Buf: TStream): string;
const
Convert: array[0..15] of Char = "0123456789ABCDEF";
var
i, p: integer;
B: byte;
begin
SetLength(Result, Buf.Size * 2);
p := Buf.Position;
Buf.Position := 0;
for i := 1 to Buf.Size do
begin
Buf.Read(B, 1);
Result[(i * 2) - 1] := Convert[B shr $4];
Result[(i * 2)] := Convert[B and $F];
end;
Buf.Position := p;
end;
procedure TForm1.Button4Click(Sender: TObject);
const
Convert: array[0..15] of Char = "0123456789ABCDEF";
var
i, p, r: integer;
B: byte;
str: string;
w,h, x,y: integer;
Stream: TFileStream;
color: tcolor;
begin
if OpenDialog1.Execute then
Stream := TFileStream.Create(OpenDialog1.FileName, fmOpenRead);
Stream.Seek(0,soFromBeginning);
redt1.Text:= StreamTohex(Stream);
Stream.Position :=0;
r := Stream.Size;
str:="$";
h := ceil(sqrt(r/3));
w := ceil(sqrt(r/3));
Image1.Picture.Bitmap.Height := h;
Image1.Picture.Bitmap.Width := w;
x:=0;
y:=0;
for i := 1 to Stream.Size do
begin
Stream.Read(B, 1);
str := str + Convert[B shr $4] + Convert[B and $F];
if (i mod 3) = 0 then
begin
color := stringToColor(str);
Image1.Picture.Bitmap.Canvas.Pixels[x,y] := color;
inc(x);
if x>w then
begin
x:=0;
inc(y);
end;
str := "$";
end;
Image1.Picture.SaveToFile("c:\test.bmp");
end;
Stream.Free;
end;
end.
← →
Германн © (2011-05-30 03:43) [20]
> Cramol (30.05.11 00:21) [19]
>
> Фух, вроде, получилось. Все работает, но проблема в том,
> что, опять же, если загружаемый файл по размеру от 100
> Кб и больше - виснет :(
>
>
Так опять читаешь с диска по одному байту.
RWolf © (29.05.11 01:55) [3] тебя смутил.
← →
VirEx © (2011-05-30 06:59) [21]>Cramol (30.05.11 00:21) [19]
чтобы не "вис", нужно запускать в отдельном потоке, и прогресбар добавить шоб юзверь не скучал
← →
Anatoly Podgoretsky © (2011-05-30 07:36) [22]> VirEx (30.05.2011 06:59:21) [21]
Пользователя этим не испугаешь, он снесет приложение через диспетчер задач.
← →
RWolf © (2011-05-30 09:38) [23]
> Anatoly Podgoretsky © (30.05.11 07:36) [22]
Ну так у автора виснет не потому, что он читает файл побайтно, а потому, что на каждое чтение байта из файла у него приходится одно сохранение картинки.
А проглядел он это потому, что игнорирует форматирование исходников.
← →
Anatoly Podgoretsky © (2011-05-30 09:41) [24]> RWolf (30.05.2011 09:38:23) [23]
Ему на это уже указавали пальце, это страшно так работать со Strings
← →
Cramol (2011-05-30 12:45) [25]Извиняюсь за бестактную наглость, но не поможете как это кодом правильно написать?
← →
Cramol (2011-05-31 20:11) [26]Видимо, нет :(
← →
Sha © (2011-05-31 22:16) [27]Чтобы сделать слегка тормознутую надо читать файл в цикле по одному байту,
хотя можно читать блоками или вообще все за один раз.
А чтобы серьезно все замедлить надо в цикле сделать что-нибудь посерьезнее,
например, сохранить какую нибудь фигню в файл.
Не надо читать справку по используемым функциям,
не надо форматировать код,
не надо читать советы [20,23], как исправить ошибки,
пусть это сделает кто-нибудь другой и даст мне код.
--
Вредные советы.
← →
Юрий Зотов © (2011-05-31 22:24) [28]> 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 сек). Только имейте в виду, что код далеко не оптимальный, поэтому разберитесь в нем и постарайтесь его улучшить.
← →
sniknik © (2011-06-01 00:24) [29]тоже не оптимально, надо бы под тип 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.
← →
sniknik © (2011-06-01 00:29) [30]> но выглядеть будет хорошо/быстро
именно выглядеть... т.к. общее время "загрузки" будет больше чем например в Юрий Зотов © (31.05.11 22:24) [28]
← →
Sha © (2011-06-01 02:04) [31]> Юрий Зотов © (31.05.11 22:24) [28]
> У меня работает со скоростью около 1 MB/sec
На моем компе чистая скорость работы цикла - 3,22 MB/sec
Если в цикле оставить только инкремент адреса - 425 MB/sec
Если переписать цикл как ниже - 322 MB/secfor i := 1 to M.Size do
begin
Q^:=H[byte(p^)];
inc(Q);
Inc(P)
end;
Если читать по 2 байта, писать по 4, используя ту же таблицу наверно будет еще быстрее.
Если при этом читать блоками или использовать MMF,
то на вычисления время вообще не потратится.
← →
Юрий Зотов © (2011-06-01 03:24) [32]
> Sha © (01.06.11 02:04) [31]
> На моем компе чистая скорость работы цикла - 3,22 MB/sec
Да, я подозревал, что значительную часть времени тратит RichEdit, но проверять не стал.
Прочие доработки, которые ты сделал (прямой адрес приемника вместо индекса символа и использование таблицы вместо IntToHex) - это и есть то, что я хотел оставить автору.
:o)
← →
Юрий Зотов © (2011-06-01 04:07) [33]В такой редакции чистая скорость цикла - около 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 раз. Это означает, что дальнейшая оптимизация цикла практического смысла не имеет.
← →
clickmaker © (2011-06-01 12:15) [34]а зачем RichEdit для hex-вида? Обычный Edit гораздо шустрее
← →
sniknik © (2011-06-01 12:39) [35]> а зачем RichEdit для hex-вида? Обычный Edit гораздо шустрее
а зачем вообще конвертировать все(?), если можно только отображаемую часть. просто автор дал такие "предпосылки"(код, который и правят, а надо логику менять, а логика она от задачи, про которую ни слова, зависит...).
← →
clickmaker © (2011-06-01 12:44) [36]> а зачем вообще конвертировать все(?), если можно только
> отображаемую часть
боюсь, тут нужен будет свой контрол для отображения. Стандартные в виртуальном режиме не работают, как известно. Хотя, извратиться попробовать можно, но перехватывать всю навигацию по тексту - задача не такая тривиальная
← →
sniknik © (2011-06-01 12:55) [37]> боюсь, тут нужен будет свой контрол для отображения.
по постановке [0] отображать тоже не нужно, просто -
> выбранный файл оказался в массиве в шестнадцатеричном виде?
а в каком виде оно будет если просто массив байт? в десятичном?
опять упираемся в задачу, что именно делается и зачем.
← →
Юрий Зотов © (2011-06-01 13:05) [38]
clickmaker © (01.06.11 12:15) [34]
> а зачем RichEdit для hex-вида? Обычный Edit гораздо шустрее
Насколько помню, обычный Edit имеет предел 64К. Или уже нет?
← →
Юрий Зотов © (2011-06-01 13:07) [39]А задача, ИМХО, просто учебная. Так что особо заморачиваться вряд ли стоит.
← →
clickmaker © (2011-06-01 13:08) [40]> Насколько помню, обычный Edit имеет предел 64К. Или уже
> нет?
это только в win9x
Страницы: 1 2 вся ветка
Форум: "Начинающим";
Текущий архив: 2011.09.18;
Скачать: [xml.tar.bz2];
Память: 0.57 MB
Время: 0.004 c