如何使用MemoryStream将TBytes转换为二进制文件?

15

我该如何使用 MemoryStreamTbytes 类型转换为 二进制文件


6
"使用MemoryStream"是一个陷阱,会使空间需求增加一倍。 - Premature Optimization
4个回答

30

或者直接使用 TFileStream,以减少创建中间对象的数量:

procedure SaveBytesToFile(const Data: TBytes; const FileName: string);
var
  Stream: TFileStream;
begin
  Stream := TFileStream.Create(FileName, fmCreate);
  try
    if Data <> nil then
      Stream.WriteBuffer(Data[0], Length(Data));
  finally
    Stream.Free;
  end;
end;

我认为在这里使用TMemoryStream并不有帮助,因为它只涉及到额外且不必要的堆内存分配/释放。


谢谢David :) 。哪个更快?使用TFileStream还是TMemoryStream.SaveToFile - Kermia
7
TMemoryStream.SaveToFile 是通过 TFileStream 来完成其工作的,最好直接使用 TFileStream 而不是中间人。 - David Heffernan
您可以考虑将 if 语句移到 try finally 外面,这样如果没有要写的内容,流就根本不会被创建。 - Uwe Raabe
@uwe,你仍然需要创建一个空文件,由于此代码已经很好地完成了这项工作,我不愿添加另一个测试,这很可能是一个罕见的特例。 - David Heffernan

13

如果没有TBytesStream可用,Uwe的答案将无效。

procedure SaveBytesToFile(const Data: TBytes; const FileName: string);
var
  stream: TMemoryStream;
begin
  stream := TMemoryStream.Create;
  try
    if length(data) > 0 then
      stream.WriteBuffer(data[0], length(data));
    stream.SaveToFile(FileName);
  finally
    stream.Free;
  end;
end;

@Kermia 你有意识到你接受了性能最差的答案吗?@Mason 请别生气! - David Heffernan
2
使用MemoryStream,我认为我应该选择相关的答案。是吗? - Kermia
@David:对于这个特定的情况,是的。但如果有很多单独的写入操作,尤其是它们很小的时候,你可以通过先将所有内容写入内存流,然后一次性块写入文件来节省大量时间。 - Mason Wheeler
@Mason 好的,我在谈论这个特定情况。至于内存流,我们经常讨论这个问题。我有自己的类来处理这个问题,比 TMemoryStream 更好,以避免地址空间碎片化问题。 - David Heffernan
1
@Kermia 我对你选择哪个答案没有意见。我只是想确保你清楚地知道,使用 TMemoryStream 是一种比必要更慢的解决方案。当你在评论中问“哪个更快?”时,这似乎与你相关。 - David Heffernan
3
顺便提一句,你使用了错误的写入方法。你应该使用WriteBuffer,因为它具有错误检查功能。我相信你知道这一点,这只是一种疏忽。 - David Heffernan

8

如果答案提到Delphi XE和其他流,而不是TMemoryStream,那么我建议再提供一种方法。

 procedure SaveBytesToFile(const Data: TBytes; const FileName: string);
 begin
   TFile.WriteAllBytes( FileName, Data );
 end;

7

在Delphi XE中的F.I.:

procedure SaveBytesToFile(const Data: TBytes; const FileName: string);
var
  stream: TBytesStream;
begin
  stream := TBytesStream.Create(Data);
  try
    stream.SaveToFile(FileName);
  finally
    stream.Free;
  end;
end;

谢谢,但我说的是:MemoryStream。没有区别吗? - Kermia
是的,你说得对。但我只是想看看这是否可能。 - Kermia
4
当你使用SaveToFile时,TBytesStream或TMemoryStream在幕后创建了一个TFileStream。最好直接像David Heffernan所示的那样直接写入TFileStream。 - PetriW
这使得它与我的答案等价。 - David Heffernan
谢谢。听起来像是一个有用的类。它是一个适配器,对吧? - David Heffernan
显示剩余7条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接