Delphi:将文件流复制到MemoryStream

Delphi:将文件流复制到MemoryStream,delphi,delphi-7,Delphi,Delphi 7,我想将文件流的一部分复制到MemoryStream FileStream.Write(Pointer(MemoryStream)^, MemoryStream.Size); FileStream.Read(Pointer(MemoryStream)^, count); 是这样吗?这对我不起作用 您必须将()从文件流读取到单独的缓冲区中,然后将()写入MemoryStream,即: var Buffer: PByte; GetMem(Buffer, NumberOfBytes); try

我想将文件流的一部分复制到MemoryStream

FileStream.Write(Pointer(MemoryStream)^, MemoryStream.Size);
FileStream.Read(Pointer(MemoryStream)^, count);
是这样吗?这对我不起作用

您必须将()从文件流读取到单独的缓冲区中,然后将()写入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分配内存缓冲区以容纳新闻大小字节[…]


我还使用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。

要格式化代码,请在编辑器中选择它,然后按Control-K。非常感谢!我用的是CopyFrom,但我认为你的解决方案会给我更好的表现。再次感谢。TStream.CopyFrom()方法在内部使用了类似的“读入缓冲区”方法,而不是“写入缓冲区”方法,但这样做的错误处理和缓冲区管理比我展示的要多。当要读取的字节数已知且固定时,应使用ReadBuffer,更好的方法是使用Read-当没有更多字节时,它实际上可以返回比缓冲区大小更少的字节。我会写:BytesRead:=FileStream.Read(Buffer^,NumberOfBytes);MemoryStream.Write(缓冲区^,字节读);由于OP想要复制文件的一部分,所以OP可能提前知道要复制多少字节。只是想帮助任何可能遇到与我相同问题的人。对于非常大的文件(>1.5GB),使用Remy posted解决方案比使用MemoryStream.CopyFrom方法快得多。我花了两天的时间想出来…:(