Delphi Перетаскивание памяти потока более 1 ГБ - PullRequest
1 голос
/ 07 сентября 2011

У меня серьезная проблема, и я застрял на этом :( Мне нужно перенести из моего приложения большие файлы (иногда более 1 ГБ) и обработать их в другое приложение, например TotalCommander или Explorer. Для этого мне нужно прочитать часть файла из исходного файла в поток, обработать его и сохранить в выходной поток. Я не могу загрузить весь файл, мне нужно прочитать около 1-30 МБ, обработать его и сохранить. Я использую Drag Drop для Delphi 7

.

Пример кода (в отчаянии я пробую много вариантов):

Var
 F13Stream : TmemoryStream;

Procedure Process_Data;
Var
 FileIn : TFileStream;
begin
 FileIn := TFileStream.Create('c:\SampleData.dat', fmOpenRead);
 Repeat
 ..read from FileIn, process data
 ..save to F13Stream
 ..write F13Stream to output? and free memory to next part data//Sorry i have no idea what to doit :(
 Until eof(source_file);
 FileIn.Free;
end;

procedure TForm13.OnGetStream(Sender: TFileContentsStreamOnDemandClipboardFormat;
  Index: integer; out AStream: IStream);
begin
 Form13.F13Stream := TMemorystream.Create;
 Process_Data;
 try
  AStream := nil;
  AStream := TFixedStreamAdapter.Create(F13Stream, soOwned);
 except
  F13Stream.Free;
  raise;
 end;
end;

procedure TForm13.LMDShellList1MouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
 TVirtualFileStreamDataFormat(DataFormatAdapterSource.DataFormat).FileNames.Clear;
 TVirtualFileStreamDataFormat(DataFormatAdapterSource.DataFormat).FileNames.Add('TestFile');
 DropEmptySource1.Execute;
end;

Это пример того, что я пытаюсь сделать. Может быть, другой компонент / код сделает это без проблем. Я могу копировать файлы без ограничений по размеру, но мне нужно частично обрабатывать большие файлы и частично отправлять другим приложениям в виде потока / массива только по памяти, а не использовать временную память дисковода. Спасибо за любую помощь.

UPDATE:

procedure TForm13.OnGetStream(Sender: TFileContentsStreamOnDemandClipboardFormat;
  Index: integer; out AStream: IStream);
var
 plk1 : TFileStream;
 buff : array[0..65535] of byte;
 read : Longint;
begin
 AStream := nil;
 Form13.F13Stream := TMemoryStream.Create;
 AStream := TFixedStreamAdapter.Create(Form13.F13Stream, soOwned);
 plk1 := TFileStream.Create('h:\Sample2GB_file.dat', fmOpenRead);
 repeat
  read := plk1.Read(buff, 65536);
  AStream.Write(@buff, read, PLongint(65536));
  AStream.SetSize(0);
 until read <> 65536;
 plk1.Free;
end;

Это тоже не работает. В результате у меня есть 0 байтов выходного файла.

UPDATE2:

Если я удалю строку: "AStream.SetSize (0);" тогда у меня ошибка «Недостаточно памяти».

1 Ответ

0 голосов
/ 24 апреля 2017

Вы не можете написать AStream в OnGetStream.Это источник IStream, который вам нужно установить, и получатель (где происходит отбрасывание) будет читать ваши данные из него.Если вам нужно обработать исходный файл, сделайте это до начала перетаскивания и сохраните результат в другом файле.Затем просто настройте новый файл в качестве источника перетаскивания.Вы можете просто сделать это в своем событии Mouse Down или, если вы предпочитаете использовать виртуальный метод, сделать это в событии OnGetStream:

procedure TForm13.OnGetStream(Sender: TFileContentsStreamOnDemandClipboardFormat;
  Index: integer; out AStream: IStream);
var
 plk1 : TFileStream;
begin
 AStream := nil;
 // TODO: Create the file to stream (read your source and save it to new_source.dat after your processing)
 plk1 := TFileStream.Create('h:\new_source.dat', fmOpenRead);
 AStream := TFixedStreamAdapter.Create(plk1, soOwned);
end;

Вы также можете создать собственный класс TStream для чтения, обработки и возвратаваши данные на лету в методе чтения.

...