簡體   English   中英

Delphi:將FileStream復制到MemoryStream

[英]Delphi: Copy FileStream to MemoryStream

我想將FileStream的一部分復制到MemoryStream。

FileStream.Write(Pointer(MemoryStream)^, MemoryStream.Size);
FileStream.Read(Pointer(MemoryStream)^, count);

那正確嗎? 它不適合我。

你必須從FileStream中將Read()放入一個單獨的緩沖區,然后將Write()放到MemoryStream中,即:

var
  Buffer: PByte;

GetMem(Buffer, NumberOfBytes);
try
  FileStream.ReadBuffer(Buffer^, NumberOfBytes);
  MemoryStream.WriteBuffer(Buffer^, NumberOfBytes);
finally
  FreeMem(Buffer);
end;

由於您正在處理兩個TStream對象,因此使用TStream.CopyFrom()方法會更容易,即:

MemoryStream.CopyFrom(FileStream, NumberOfBytes);

以下解決方案不使用單獨的緩沖區作為已發布的解決方案。 而是直接寫入目標內存流的緩沖區。 這是更快的,因為另一個解決方案復制兩次,首先進入臨時緩沖區,最后進入內存流。

...
try
  MemoryStream.SetSize(NumberOfBytes); // Allocating buffer
  FileStream.ReadBuffer(MemoryStream.Memory^, NumberOfBytes);
finally
  MemoryStream.Free();
...

這是有效的,因為SetSize還分配內存流的緩沖區。 請參閱SetSize文檔

使用SetSize在填充數據之前設置內存流的大小。 SetSize分配內存緩沖區以保存NewSize字節[...]。


我還使用CopyFrom測試了該解決方案,但該解決方案使用巨型文件非常慢,因為它似乎使用非常小的緩沖區。

如果要使用上面的方法直接讀取文件,可以使用自己的函數來完成,該函數直接將塊讀取到內存流中。 為了比CopyFrom方法更快,這些塊應該更大。 以下代碼使用靈活的緩沖區,例如256 MiB。 請隨意使用它。

var
  ...
  MemoryStreamPointer: Pointer;
  BlockSize: Integer;
  BytesToRead: Integer;
  BytesRead: Integer;
  RemainingBytes: Integer;

begin
  ...
  BlockSize := 256 * 1024 * 1024; // 256 MiB block size

  MemoryStream.SetSize(NumberOfBytes); // Allocating buffer
  MemoryStreamPointer := MemoryStream.Memory;

  RemainingBytes := NumberOfBytes;
  while RemainingBytes > 0 do
  begin
    BytesToRead := min(RemainingBytes, BlockSize);
    BytesRead := FileStream.Read(MemoryStreamPointer^, BytesToRead);
    RemainingBytes := RemainingBytes - BytesRead;
    MemoryStreamPointer := Pointer(NativeInt(MemoryStreamPointer) + BytesRead);
  end;
  ...
end;

請注意,上面的代碼不包含錯誤處理。 進一步考慮在讀取之前將文件流位置設置為0。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM