Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2011.09.18;
Скачать: CL | DM;

Вниз

Представить файл в 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/sec
       for 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;
Скачать: CL | DM;

Наверх




Память: 0.58 MB
Время: 0.012 c
2-1306920985
R_R
2011-06-01 13:36
2011.09.18
Печать в QuickRep


15-1306654677
ddd329
2011-05-29 11:37
2011.09.18
Трехзвенка в C#


8-1216548902
Паша123
2008-07-20 14:15
2011.09.18
Вывод текста по синусу


2-1306852612
MenuItem.Bitmap
2011-05-31 18:36
2011.09.18
Динамически поменять Bitmap у элемента TMenuItem


8-1187098476
leonidus
2007-08-14 17:34
2011.09.18
Где найти компонент отображающий Thumbnail ?