Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Оптимизация побайтового чтения и сравнения двух бинарных файлов / 25 сообщений из 112, страница 1 из 5
19.12.2017, 15:11
    #39572066
Bellic
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация побайтового чтения и сравнения двух бинарных файлов
Прошу знатоков помочь с оптимизацией побайтового чтения и сравнения двух бинарных файлов!

Ниже приведен несколько урезанный код самой процедуры...
(прошу не пинать за возможно большой код... но иначе возможно было бы больше от Вас уточнений и ухода темы в сторону)

Данная тема перекликается с моей же темой " Вывод в Memo японских иероглифов (932-я кодовая таблица) ", но об этом позже.

Немного словесного описания:
Процедура оперирует двумя бинарными файлами одинаковой длины:
- OriginalFile - бинарный файл в котором встречаются английские и японские текстовые фразы (в 932 или 20932 -й кодировке) с лидирующими и замыкающими нулевыми байтами;
- PerevedenFile - бин.файл созданный на основе предыдущего Оригинала, но японские фразы заменены на их английские аналоги, т.е. Переведены с учетом длины японской фразы включая Пред.и После-нули. Данный файл может быть "переведен" предварительно вручную или др.программой, это не важно!

Задача процедуры - на основании информации из файлов OriginalFile и PerevedenFile сформировать текстовый файл PerevodFile со структурой, упрощенно похожей на XML, который можно будет открывать для просмотра в текстовом редакторе (в дальнейшем буду иметь ввиду " Notepad++ "), так и в "WinHex".

Пришло время привести тестовые примеры этих Трех файлов, а затем - структуру выходного файла PerevodFile !?

OriginalFile :


PerevedenFile :


PerevodFile :


Но лучше на него взглянуть из " Notepad++ " (включена индикация "Всех" символов):
Эхх - картинка длинная получилась!..((( Надеюсь на 14'-вом монике никто не читает?..)

Или можно скопировать его сюда:
Код: xml
1.
2.
*#0082B182F182C982BF82CD000000#00476F6F64206D6F726E696E6700#こんにちは#Good morning#...You comments...##
*#00834F836283688378834300#00476F6F6420626179000000#グッドベイ#Good bay#...You comments...##

Правда упр.символов " CR " " LF " тут видно не будет!
Иероглифы скорее всего - тоже не проявятся..((
Тогда попробую еще просто вставить (да простят меня Модераторы и Админы форума!):

*#0082B182F182C982BF82CD000000#00476F6F64206D6F726E696E6700#こんにちは#Good morning#...You comments...##
*#00834F836283688378834300#00476F6F6420626179000000#グッドベイ#Good bay#...You comments...##


Внимательные глаза возможно уже сами увидели формат выходного файла!?..))
Сейчас останавливаться на нем больше не буду, если надо будет - распишу его структуру!

Зачем я это все пишу и вставляю картинки?
Да просто опережаю время, предвидя возможные наводящие вопросы и уточнения - стараюсь выложить всю начальную информацию!

Ну а тем, кто дочитал до этого места - собственно попробую сформулировать свой вопрос согласно топика...


Как видите - для чтения отдельных байт из файлов я использовал TFileStream , просто на этапе правильного составления алгоритма, так было удобней и легче!
Но читать по одному байту - как то не очень шустро получается!
Подскажите пожалуйста, для реализации данного алгоритма - какие варианты можно еще попробовать???

А тут сам код процедуры:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
//------------------------------------------------------------------------------------------
procedure TMainForm.MainProcess(Sender: TObject);
var
SizeOriginal, SizePereveden: Integer;
Address: Integer;
SizeFraza: Integer;
NumberString: Integer; // Номер строки Перевода
i: Integer;
FrazaOk: Boolean; // Флаг найденного различия в фразах
begin
     MainMemo.Lines.Clear;
     // Считываем имена файлов из Полей редактирования (возможно редактировались!)
     FullOriginalFileName := FileBinOriginalEdit.Text;
     FullPerevedenFileName := FileBinPerevedenEdit.Text;
     FullPerevodFileName := DirPerevodEdit.Text + PerevodFileNameEdit.Text;

     try
          FOriginal:=TFileStream.Create(FullOriginalFileName, fmOpenRead, fmshareCompat);
          SizeOriginal := FOriginal.Size;
          FPereveden:=TFileStream.Create(FullPerevedenFileName, fmOpenRead, fmshareCompat);
          SizePereveden := FPereveden.Size;

          if SizeOriginal <> SizePereveden then
               begin  MainMemo.Lines.Add('Длины BIN-файлов НЕ РАВНЫ! Продолжение Невозможно!');
                      Exit;
               end;
          AddressFiles := 0;
          NumberString := 0;

          while AddressFiles < SizeOriginal do
               begin
                    TwoBytesRead(MainForm);  // Читаем ISimvol и PSimvol

                    if (ISimvol=0) and (PSimvol=0) then
                         begin
                              Address := AddressFiles;
                              SizeFraza := 1;
                              Inc(AddressFiles);
                              if AddressFiles >= SizeOriginal then Exit;

                              TwoBytesRead(MainForm);  // Читаем ISimvol и PSimvol

                              if (ISimvol<>0) and (PSimvol<>0) then
                                   begin
                                        FrazaOk:=False; // Сбрасываем флаг перед анализом.
                                        repeat
                                             if ISimvol<>PSimvol then FrazaOk:=True; // Нашли Разные байты в фразах

                                             Inc(SizeFraza);
                                             Inc(AddressFiles);

                                             if AddressFiles >= SizeOriginal then Exit;

                                             TwoBytesRead(MainForm);  // Читаем ISimvol и PSimvol
                                        until (ISimvol=0) and (PSimvol=0);

                                        if FrazaOk=True then
                                             begin
                                                  Inc(SizeFraza);
                                                  Inc(NumberString);

                                                  // Первые два Символа строки: "*#"
                                                  MainMemo.Lines.Add('*#');

                                                  // Пишем Исходные (JP_HEX)-----------------------------
                                                  for i:=0  to SizeFraza-1 do
                                                       begin
                                                            FOriginal.Seek((Address + i), soFromBeginning);
                                                            FOriginal.ReadBuffer(ISimvol,1);

                                                            MainMemo.Lines[MainMemo.Lines.Count-1]:=MainMemo.Lines[MainMemo.Lines.Count-1] +
                                                            IntToHex(ISimvol, 2);
                                                       end;
                                                  MainMemo.Lines[MainMemo.Lines.Count-1]:=MainMemo.Lines[MainMemo.Lines.Count-1] + '#';

                                                  // Пишем переведенные (ENG_HEX)------------------------
                                                  for i:=0  to SizeFraza-1 do
                                                       begin
                                                            FPereveden.Seek((Address + i), soFromBeginning);
                                                            FPereveden.ReadBuffer(PSimvol,1);

                                                            MainMemo.Lines[MainMemo.Lines.Count-1]:=MainMemo.Lines[MainMemo.Lines.Count-1] +
                                                            IntToHex(PSimvol, 2);
                                                       end;
                                                  MainMemo.Lines[MainMemo.Lines.Count-1]:=MainMemo.Lines[MainMemo.Lines.Count-1] + '#';

                                                  // Пишем исходные байты (JP_TXT)-----------------------
                                                  for i := 1 to SizeFraza-2 do
                                                       begin
                                                            FOriginal.Seek((Address + i), soFromBeginning);
                                                            FOriginal.ReadBuffer(ISimvol,1);

                                                            // Если это LF, то меняем его на "@"
                                                            if ISimvol=10 then ISimvol := 64; // 40 hex

                                                            MainMemo.Lines[MainMemo.Lines.Count-1]:=MainMemo.Lines[MainMemo.Lines.Count-1] +
                                                            AnsiChar(ISimvol);
                                                       end;
                                                  MainMemo.Lines[MainMemo.Lines.Count-1]:=MainMemo.Lines[MainMemo.Lines.Count-1] + '#';

                                                  // Пишем переведенные байты (ENG_TXT)------------------
                                                  for i := 1 to SizeFraza-2 do
                                                       begin
                                                            FPereveden.Seek((Address + i), soFromBeginning);
                                                            FPereveden.ReadBuffer(ISimvol,1);

                                                            // Если это LF, то меняем его на "@"
                                                            if ISimvol=10 then ISimvol := 64; // 40 hex

                                                            MainMemo.Lines[MainMemo.Lines.Count-1]:=MainMemo.Lines[MainMemo.Lines.Count-1] +
                                                            AnsiChar(ISimvol);
                                                       end;
                                                  MainMemo.Lines[MainMemo.Lines.Count-1]:=MainMemo.Lines[MainMemo.Lines.Count-1] +
                                                   '#' + '...You comments...' + '##';
                                             end;
                                   end;
                         end
                     else
                         begin
                              Inc(AddressFiles);
                         end;
               end;
     finally
          FOriginal.Free;
          FPereveden.Free;

          MainMemo.Lines.SaveToFile(FullPerevodFileName); // Сохраняем Мемо в файл
          MainMemo.Lines.Add('Файл-Переводов "'+ FullPerevodFileName + ' записан!');

          if DublicateDel=True then // Если флаг УдаленияДублей=1, удаляем дубли
               begin  MainMemo.Lines.Add('Удаляем дубликаты строк в Файле-Переводов... "');
                         DublicateDelete(MainForm); // Процедура удаления дубликатов строк
               end;
          MainMemo.Lines.Add('Обработка файлов завершена!');
          if NumberString=0 then MainMemo.Lines.Add('Различий в Двоичных файлах не найдено!')
          else MainMemo.Lines.Add('Найдено Фраз-Перевода: ' + IntToStr(NumberString));
     end;
end;
//----------------------------------------------------------------------------------------------------


Для побайтного-посимвольного накопления выходного файла я использовал TMemo с последующей процедурой удаления дублей строк (ее текст тут упущен..) и выгрузкой его в файл.
Хотя наверное для этого можно использовать и TStringList !? - Надо попробовать его.

Формат получаемого файла " Perevod " полностью меня устраивает, единственное, что никак не могу понять:

MainMemo :


При выводе в TMemo всего этого "bla-bla-bla...", вместо японских иероглифов присутствую совсем другие символы!
(А в свойствах TMemo.Font зачем тогда присутствует выбор кодировки, в том числе 932 !? )

НО!!! - Вопрос по TMemo.Font - это совсем другая история и я уже начал по ней дискуссию ТАМ .

P.S. В данном топике меня интересует прежде всего - варианты оптимизации чтения!
(Ну а дальше - что позволят уважаемые Модераторы...)
...
Рейтинг: 0 / 0
19.12.2017, 15:41
    #39572100
wadman
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация побайтового чтения и сравнения двух бинарных файлов
BellicПодскажите пожалуйста, для реализации данного алгоритма - какие варианты можно еще попробовать???
Можно начать отсюда https://www.google.com/search?q=delphi buffered file stream
...
Рейтинг: 0 / 0
19.12.2017, 16:07
    #39572120
Гаджимурадов Рустам
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация побайтового чтения и сравнения двух бинарных файлов
Bellic(Ну а дальше - что позволят уважаемые Модераторы...)
Модератор настоятельно советует не злоупотреблять оформлением.
...
Рейтинг: 0 / 0
19.12.2017, 18:52
    #39572240
SOFT FOR YOU
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация побайтового чтения и сравнения двух бинарных файлов
Bellic,

Я нифига не понял, чего тебе нужно. Изложи вопрос компактнее, пожалуйста

От себя замечу, что UniConv поддерживает 932 и 20932 кодировки. А значит и CachedTexts поддерживает их.
Значит ты можешь делать построчные Readln и вообще как угодно работать с текстом. Хоть через автокоррекцию в UTF8, хоть в Unicode, хоть в 51949
...
Рейтинг: 0 / 0
19.12.2017, 21:24
    #39572293
utf8 ? ... ...
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация побайтового чтения и сравнения двух бинарных файлов
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
var
 LPos : Int64;
 ISymbol, PSymbol : Byte;
begin
 OpenFiles();
 if FOriginal.Size = FPereveden.Size then
    for LPos := 0 to FOriginal.Size div SizeOf(ISymbol) - 1 do begin
        FOriginal.Read(ISymbol, SizeOf(ISymbol));
        FPereveden.Read(PSymbol, SizeOf(PSymbol));
        if ISymbol<>PSymbol then Break;
    end;
 CloseFiles();
end;
...
Рейтинг: 0 / 0
19.12.2017, 21:55
    #39572307
Док
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация побайтового чтения и сравнения двух бинарных файлов
SOFT FOR YOUUniConv поддерживает 932 и 20932 кодировки. А значит и CachedTexts поддерживает их.
дальше все про блох....
...
Рейтинг: 0 / 0
20.12.2017, 10:28
    #39572513
Bellic
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация побайтового чтения и сравнения двух бинарных файлов
wadmanМожно начать отсюда https://www.google.com/search?q=delphi buffered file stream
wadman , Вам - большое спасибо за подсказку, а разработчикам за такой подарок - давно бы стоило это сделать!..)

Замена TFileStream на TBufferedFileStream на тестовом примере от сюда ( Faster FileStream with TBufferedFileStream ) выдала офигительный результат - вместо 2491 msec, тест сработал за 31 msec (это более чем в 80 раз быстрее!)
Только автор что-то там не так немного с подсчетом символа "#13" накрутил..) - я не стал разбираться.
Тестовый код из статьи
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
unit MainModule;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
  Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, System.Diagnostics, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    Memo1: TMemo;
    btnWrite: TButton;
    btnRead: TButton;
    btnReadBuffered: TButton;
    procedure btnWriteClick(Sender: TObject);
    procedure btnReadClick(Sender: TObject);
    procedure btnReadBufferedClick(Sender: TObject);

  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

//==============================================================================
procedure TForm1.btnWriteClick(Sender: TObject);
var
  sw: TStreamWriter;
  I: Integer;
begin
  sw := TStreamWriter.Create('test.txt', False, TEncoding.UTF8);
  try
    // write 10K lines
    sw.WriteLine ('Hello, world');
    for I := 1 to 99999 do
      sw.WriteLine ('Hello ' + I.ToString);
 finally
   sw.Free;
 end;
 Memo1.Lines.Add ('File written');

end;
//==============================================================================
procedure TForm1.btnReadClick(Sender: TObject);
var
 fStr: TFileStream;
 Total, I: Integer;
 sw: TStopwatch;
 ch: Char;
begin
  sw := TStopwatch.StartNew;
  fStr := TFileStream.Create('test.txt', fmOpenRead);
  try
    Total := 0;
    while fStr.Read (ch, 1) = 1 do begin
      if ch = #13 then
        Inc(Total);
    end;
    Memo1.Lines.Add ('Lines: ' + Total.ToString);
  finally
    fStr.Free;
  end;
  sw.Stop;
  Memo1.Lines.Add ('msec: ' + sw.ElapsedMilliseconds.ToString);

end;
//==============================================================================
procedure TForm1.btnReadBufferedClick(Sender: TObject);
var
  fStr: TBufferedFileStream;
  Total, I: Integer;
  sw: TStopwatch;
  ch: Char;
begin
  sw := TStopwatch.StartNew;
  fStr := TBufferedFileStream.Create('test.txt', fmOpenRead);
  try
    Total := 0;
    while fStr.Read (ch, 1) = 1 do
     begin
      if ch = #13 then
        Inc(Total);
     end;
    Memo1.Lines.Add ('Lines: ' + Total.ToString);
  finally
    fStr.Free;
  end;
  sw.Stop;
  Memo1.Lines.Add ('msec: ' +   sw.ElapsedMilliseconds.ToString);

end;
//==============================================================================
end.

Правда чтоб это работало - необходима свежая редакция Delphi - у меня стоит XE3 и 10.2.
...
Рейтинг: 0 / 0
20.12.2017, 11:08
    #39572565
|:|
|:|
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация побайтового чтения и сравнения двух бинарных файлов
BellicДля побайтного-посимвольного накопления выходного файла я использовал TMemo Bellic... выдала офигительный результат - вместо 2491 msec, тест сработал за 31 msec (это более чем в 80 раз быстрее!)
...
Рейтинг: 0 / 0
20.12.2017, 11:35
    #39572596
alekcvp
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация побайтового чтения и сравнения двух бинарных файлов
Глянул на исходники...

Я уже писал вам в другой теме, что код вида
Код: pascal
1.
2.
3.
4.
5.
6.
for i := 0 to SizeFraza - 1 do
begin
  FOriginal.Seek((Address + i), soFromBeginning);
  FOriginal.ReadBuffer(ISimvol, 1);
  MainMemo.Lines[MainMemo.Lines.Count-1] := MainMemo.Lines[MainMemo.Lines.Count-1] + IntToHex(ISimvol, 2);
end;

и слово "скорость", взаимосвязаны примерно как гиппопотам и стратосферные полёты.

Ради интереса, запустите своё приложение в режиме отладчика (с включенной опцией Use Debug DCUs ) и пройдитесь кнопкой F7 (Trace Into) по этому циклу, посмотрите сколько и какого кода там выполняется.
...
Рейтинг: 0 / 0
20.12.2017, 12:07
    #39572627
SoftForYou
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация побайтового чтения и сравнения двух бинарных файлов
BellicwadmanМожно начать отсюда https://www.google.com/search?q=delphi buffered file stream
wadman , Вам - большое спасибо за подсказку, а разработчикам за такой подарок - давно бы стоило это сделать!..)

Замена TFileStream на TBufferedFileStream на тестовом примере от сюда ( Faster FileStream with TBufferedFileStream ) выдала офигительный результат - вместо 2491 msec, тест сработал за 31 msec (это более чем в 80 раз быстрее!)
Только автор что-то там не так немного с подсчетом символа "#13" накрутил..) - я не стал разбираться.
Тестовый код из статьи
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
unit MainModule;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
  Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, System.Diagnostics, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    Memo1: TMemo;
    btnWrite: TButton;
    btnRead: TButton;
    btnReadBuffered: TButton;
    procedure btnWriteClick(Sender: TObject);
    procedure btnReadClick(Sender: TObject);
    procedure btnReadBufferedClick(Sender: TObject);

  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

//==============================================================================
procedure TForm1.btnWriteClick(Sender: TObject);
var
  sw: TStreamWriter;
  I: Integer;
begin
  sw := TStreamWriter.Create('test.txt', False, TEncoding.UTF8);
  try
    // write 10K lines
    sw.WriteLine ('Hello, world');
    for I := 1 to 99999 do
      sw.WriteLine ('Hello ' + I.ToString);
 finally
   sw.Free;
 end;
 Memo1.Lines.Add ('File written');

end;
//==============================================================================
procedure TForm1.btnReadClick(Sender: TObject);
var
 fStr: TFileStream;
 Total, I: Integer;
 sw: TStopwatch;
 ch: Char;
begin
  sw := TStopwatch.StartNew;
  fStr := TFileStream.Create('test.txt', fmOpenRead);
  try
    Total := 0;
    while fStr.Read (ch, 1) = 1 do begin
      if ch = #13 then
        Inc(Total);
    end;
    Memo1.Lines.Add ('Lines: ' + Total.ToString);
  finally
    fStr.Free;
  end;
  sw.Stop;
  Memo1.Lines.Add ('msec: ' + sw.ElapsedMilliseconds.ToString);

end;
//==============================================================================
procedure TForm1.btnReadBufferedClick(Sender: TObject);
var
  fStr: TBufferedFileStream;
  Total, I: Integer;
  sw: TStopwatch;
  ch: Char;
begin
  sw := TStopwatch.StartNew;
  fStr := TBufferedFileStream.Create('test.txt', fmOpenRead);
  try
    Total := 0;
    while fStr.Read (ch, 1) = 1 do
     begin
      if ch = #13 then
        Inc(Total);
     end;
    Memo1.Lines.Add ('Lines: ' + Total.ToString);
  finally
    fStr.Free;
  end;
  sw.Stop;
  Memo1.Lines.Add ('msec: ' +   sw.ElapsedMilliseconds.ToString);

end;
//==============================================================================
end.

Правда чтоб это работало - необходима свежая редакция Delphi - у меня стоит XE3 и 10.2.

Чё-то не понял, у тебя же файл японский, а не юникодовый. Почему ты читаешь Char?
...
Рейтинг: 0 / 0
20.12.2017, 12:09
    #39572631
SoftForYou
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация побайтового чтения и сравнения двух бинарных файлов
И какой вообще смысл читать посимвольно файл?
...
Рейтинг: 0 / 0
20.12.2017, 12:34
    #39572658
SoftForYou
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация побайтового чтения и сравнения двух бинарных файлов
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
type
  TJapaneesTextReader = class(TUTF16TextReader)
  public
    constructor Create(const Source: TCachedReader; const Owner: Boolean);
    constructor CreateFromFile(const FileName: string);
  end;

constructor TJapaneesTextReader.Create(const Source: TCachedReader; const Owner: Boolean);
var
  Context: PUniConvContext;
begin
  Context := Self.GetInternalContext;
  Context.Init(CODEPAGE_UTF16, 20932, ccOriginal);
  CreateDirect(Context, Source, Owner);
end;

constructor TJapaneesTextReader.CreateFromFile(const FileName: string);
begin
  FFileName := FileName;
  Create(TCachedFileReader.Create(FileName), True);
end;



А потом читаешь построчно:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
var
  S: UTF16String{быстрее} или UnicodeString; 
  Reader: TJapaneesTextReader;
begin
  Reader := TJapaneesTextReader.CreateFromFile(имя файла);
  try
    while Reader.Readln(S) do
    begin
      // ToDo
    end;
  finally
    Reader.Free;
  end;
end;



А посимвольно можно так. Для Char (WideChar) можно сделать быстрее, только расписывать не буду :)
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
var
  C: UCS4Char;
  Reader: TJapaneesTextReader;
begin
  Reader := TJapaneesTextReader.CreateFromFile(имя файла);
  try
    while not Reader.EOF do
    begin
      C := Reader.ReadChar;
      // ToDo
    end;
  finally
    Reader.Free;
  end;
end;
...
Рейтинг: 0 / 0
20.12.2017, 12:38
    #39572664
Bellic
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация побайтового чтения и сравнения двух бинарных файлов
alekcvpГлянул на исходники...

Я уже писал вам в другой теме, что код вида
Код: pascal
1.
2.
3.
4.
5.
6.
for i := 0 to SizeFraza - 1 do
begin
  FOriginal.Seek((Address + i), soFromBeginning);
  FOriginal.ReadBuffer(ISimvol, 1);
  MainMemo.Lines[MainMemo.Lines.Count-1] := MainMemo.Lines[MainMemo.Lines.Count-1] + IntToHex(ISimvol, 2);
end;

и слово "скорость", взаимосвязаны примерно как гиппопотам и стратосферные полёты.

Ради интереса, запустите своё приложение в режиме отладчика (с включенной опцией Use Debug DCUs ) и пройдитесь кнопкой F7 (Trace Into) по этому циклу, посмотрите сколько и какого кода там выполняется.
Рано я обрадовался!!!
Замена TFileStream на TBufferedFileStream в реальной процедуре скорости ей не прибавила, и даже наоборот (было 193 сек, а стало - 196 сек)!

И с Вам, alekcvp , я тоже полностью согласен, что вышеуказанный цикл "гиппопотамовский"!

Индикация в Memo в принципе вообще не нужна, а произвести формирование Выходного файла думаю можно и в TStringList , а потом командой SaveToFile сохранить его в файле!?
...
Рейтинг: 0 / 0
20.12.2017, 12:47
    #39572669
Bellic
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация побайтового чтения и сравнения двух бинарных файлов
SoftForYouЧё-то не понял, у тебя же файл японский, а не юникодовый. Почему ты читаешь Char?
Вообще то читаю и анализирую побайтно (ISimvol, PSimvol: Byte;) потому, что в Исходных файлах могут быть не только 2-х байтные, но и 1-байтные японские символы (932 и 20932-й кодировок), латиница, а так же просто например машинный код для процессора!

SoftForYou , я ответил на Ваш вопрос?
...
Рейтинг: 0 / 0
20.12.2017, 12:52
    #39572675
Bellic
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация побайтового чтения и сравнения двух бинарных файлов
SoftForYouИ какой вообще смысл читать посимвольно файл?
Исходные файлы OriginalFile и PerevedenFile - это Бинарники, а не Текстовые!
Это вообще-то "прошивки" для электронных устройств (машинный код!) с некоторым числом Текстовых фраз!
По другому тут я думаю никак не получится!
...
Рейтинг: 0 / 0
20.12.2017, 14:38
    #39572759
Оптимизация побайтового чтения и сравнения двух бинарных файлов
Bellicэто Бинарники, а не Текстовые!Bellic, методичку по массивам почитай ))
...
Рейтинг: 0 / 0
20.12.2017, 14:57
    #39572776
SoftForYou
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация побайтового чтения и сравнения двух бинарных файлов
Bellic,

Тогда тебе нужен CachedBuffers
По сути тебе нужен только CachedBuffers.pas

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
var
  B: Byte;
  Reader: TCachedFileReader;
begin
  Reader := TCachedFileReader.Create(имя файла);
  try
    while (not Reader.EOF) do
    begin
      Reader.ReadData(B);
      // ToDo
    end;
  finally
    Reader.Free;
  end;



Это самый быстрый способ побайтного чтения твоих файлов
Но я думаю, скорость у тебя проседает не на чтении файлов, а в каких-то других местах, например, при переводе строки в юникод
...
Рейтинг: 0 / 0
20.12.2017, 16:43
    #39572915
ОнСамый
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация побайтового чтения и сравнения двух бинарных файлов
Попкорновый файлBellicэто Бинарники, а не Текстовые!Bellic, методичку по массивам почитай ))
На предмет чего?
...
Рейтинг: 0 / 0
21.12.2017, 01:16
    #39573188
Bellic
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация побайтового чтения и сравнения двух бинарных файлов
Думал насчет использования массивов, но пока решил повременить...

В общем отказался от TMemo для "формирования и накопления" строк и последующего сохранения его в файл...
(Вывод в TMemo оставил только для информационных сообщений)
Чтение бинарников оставил через TFileStream .

Сейчас это выглядит примерно так:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
MString: TStrings;
SStroka: AnsiString;
...
MString := TStringList.Create;
...
SStroka := '*#';
...
for i := 0 to SizeFraza - 1 do
begin
  FOriginal.Seek((Address + i), soFromBeginning);
  FOriginal.ReadBuffer(ISimvol, 1);
  //MainMemo.Lines[MainMemo.Lines.Count-1] := 
  //      MainMemo.Lines[MainMemo.Lines.Count-1] + IntToHex(ISimvol, 2);
  SStroka := SStroka + IntToHex(ISimvol, 2);
end;
...
MString.Add(SStroka);
...
MString.SaveToFile(FileName);


В результате - время выполнения процедуры от 193 секунд уменьшилось до 87 !
(Забыл ранее упомянуть, что размер бинарников - каждый примерно по 10 Мбайт )

В принципе - результатом более или менее доволен, но думаю что можно еще подчистит код или попробовать другие варианты реализации, в том числе и с Массивами!
...
Рейтинг: 0 / 0
21.12.2017, 09:13
    #39573273
wadman
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация побайтового чтения и сравнения двух бинарных файлов
Bellic(Забыл ранее упомянуть, что размер бинарников - каждый примерно по 10 Мбайт )
Копейки... Можно разом загрузить и не дергать чтение по байтам.
...
Рейтинг: 0 / 0
21.12.2017, 10:53
    #39573343
alekcvp
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация побайтового чтения и сравнения двух бинарных файлов
BellicСейчас это выглядит примерно так:
Код: pascal
1.
2.
3.
4.
for i := 0 to SizeFraza - 1 do
begin
  FOriginal.Seek((Address + i), soFromBeginning);
  FOriginal.ReadBuffer(ISimvol, 1);



1. При последовательном чтении Seek() делать не надо, Read[Buffer]() сама переносит указатель на Count позиций вперёд.
2. Для разнообразия:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
  const
    HexChars: array [0..15] of AnsiChar = '0123456789ABCDEF';
  var
    Buffer: TBytes;
    SStroka: AnsiString;
  ...
  SetLength(SStroka, (SizeFraza + 1) * 2);
  SStroka[1] := '*';
  SStroka[2] := '#';  
  ... 
  SetLength(Buffer, SizeFraza);
  FOriginal.Seek(Address, soFromBeginning);
  FOriginal.ReadBuffer(Buffer[0], SizeFraza); // чтение не побайтное, а одним куском
  for i := 0 to SizeFraza - 1 do begin
    SStroka[i * 2 + 3] := HexChars[Buffer[i] shr 4];
    SStroka[i * 2 + 4] := HexChars[Buffer[i] and $0F];
  end;
...
Рейтинг: 0 / 0
21.12.2017, 11:48
    #39573396
SOFT FOR YOU
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация побайтового чтения и сравнения двух бинарных файлов
Bellic,

Загрузи исходные файлы в память, так будет быстрее и удобнее
А запись в файл у тебя очень долгая - ты постоянно перевыделяешь строки и используешь конкатенацию. Тебе нужно использовать TCachedTextWriter и TTemporaryString. В общем не очень ясно, зачем ты у нас что-то спрашиваешь, если вообще не прислушиваешься к тому, что мы говорим :)
...
Рейтинг: 0 / 0
21.12.2017, 13:23
    #39573535
Bellic
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация побайтового чтения и сравнения двух бинарных файлов
SoftForYouBellic,
Тогда тебе нужен CachedBuffers
По сути тебе нужен только CachedBuffers.pas
я так понимаю - это компонент? Возможно попробую чуть позже... правда это утяжелит программу...

wadman..Можно разом загрузить и не дергать чтение по байтам.
Думаю Вы правы! Но в 2-х циклах из 4-рех идет не только побайтное чтение, но и анализ этих данных, да и обвязка для "загрузки разом" будет стоить некоторого кода..(

alekcvp1. При последовательном чтении Seek() делать не надо, ReadBuffer]() сама переносит указатель на Count позиций вперёдЭто известно мне, Seek() остался от вырисовывания алгоритма, сейчас приведу в порядок где это возможно. Спасибо за подсказку!

alekcvp
2. Для разнообразия:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
  const
    HexChars: array [0..15] of AnsiChar = '0123456789ABCDEF';
  var
    Buffer: TBytes;
    SStroka: AnsiString;
  ...
  SetLength(SStroka, (SizeFraza + 1) * 2);
  SStroka[1] := '*';
  SStroka[2] := '#';  
  ... 
  SetLength(Buffer, SizeFraza);
  FOriginal.Seek(Address, soFromBeginning);
  FOriginal.ReadBuffer(Buffer[0], SizeFraza); // чтение не побайтное, а одним куском
  for i := 0 to SizeFraza - 1 do begin
    SStroka[i * 2 + 3] := HexChars[Buffer[i] shr 4];
    SStroka[i * 2 + 4] := HexChars[Buffer[i] and $0F];
  end

;
Это еще не совсем понял, разберусь думаю..

SOFT FOR YOUЗагрузи исходные файлы в память, так будет быстрее и удобнееОтличная идея!!! Следующий вариант попробую именно его!
А запись в файл у тебя очень долгая - ты постоянно перевыделяешь строки и используешь конкатенацию.Конкатенацию юзать удобно - не надо следить за указателем позиции.
А запись в файл в свете варианта использования " TStringList ", выглядит одной строкой:
Код: pascal
1.
MString.SaveToFile(FileName);


Тебе нужно использовать TCachedTextWriter и TTemporaryString. В общем не очень ясно, зачем ты у нас что-то спрашиваешь, если вообще не прислушиваешься к тому, что мы говорим :)
SOFT FOR YOU , я думаю Вы зря обвиняете меня в невнимательности к предложениям пользователей!
Замену TFileStream на TBufferedFileStream попробовал;

От TMemo с позицированием в нем (типа " Memo.Lines[Memo.Lines.Count-1]:=Memo.Lines[Memo.Lines.Count-1] + '#'; ") тоже избавился.

Массив частично заюзал - " SStroka: AnsiString; " - это же по сути тот же массив, но символьный!?

...при возможности - обязательно попробую предложенные Вами варианты...

P . S . К сожалению (или к счастью?!) мы все люди (как ни странно...), а не машины!
У каждого свои достоинства, недостатки и Время - для их приумножения или искоренения!...
Спасибо Всем, за то что Вы сейчас со мной, здесь и сейчас!!!
...
Рейтинг: 0 / 0
21.12.2017, 16:48
    #39573834
makhaon
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация побайтового чтения и сравнения двух бинарных файлов
Bellic,

>Конкатенацию юзать удобно - не надо следить за указателем позиции.

Удобно, но медленно. Указатель - всего лишь одна переменная + 1-2 строки кода. Многократное ускорение стоят того, что бы разобраться.
...
Рейтинг: 0 / 0
21.12.2017, 17:37
    #39573898
Bellic
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация побайтового чтения и сравнения двух бинарных файлов
makhaonBellic,

>Конкатенацию юзать удобно - не надо следить за указателем позиции.

Удобно, но медленно. Указатель - всего лишь одна переменная + 1-2 строки кода. Многократное ускорение стоят того, что бы разобраться.
Ну я не стою на месте...
Правда неудачно "выкосил" Seek , в результате чего сломался алгоритм и в выходном файле появились ошибочные данные...((
Будет время - пройдусь пошагово на тестовых файлах...
А уже после этого - буду думать что еще можно оптимизировать! Хотелось бы дорешать этот вариант!
...
Рейтинг: 0 / 0
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Оптимизация побайтового чтения и сравнения двух бинарных файлов / 25 сообщений из 112, страница 1 из 5
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]