Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 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/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;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.57 MB
Время: 0.004 c
15-1306509683
Чайник
2011-05-27 19:21
2011.09.18
Не включается монитор


15-1306320156
clickmaker
2011-05-25 14:42
2011.09.18
Как в ICQ 7.5 отключить открытие по Ctrl+Shift+I


15-1306064953
Архип
2011-05-22 15:49
2011.09.18
Помогите с С на Делфи перевести?


2-1306949786
Григорий
2011-06-01 21:36
2011.09.18
помогите накодить штуку(


2-1306677371
Justin
2011-05-29 17:56
2011.09.18
Как определить соотношение ширина/высота?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский