如何在Delphi 7中将内存流转换为文件流?

时间:2018-07-18 13:36:42

标签: delphi filestream memorystream

我有这段代码,我正在其中将缓冲区读取到内存流中,并且想要将其保存到文件流中。问题是memoryStream.GetBuffer()不适用于我的Delphi 7,因为它是未声明的标识符。

procedure Dictionary.WriteHeaderObj(filename: String);
var MemStream: TMemoryStream;
    i: Integer;
begin
  self.fileName := filename;

  try
    MemStream := TMemoryStream.Create;
    try
      fsOutput := TFileStream.Create(fileName, fmCreate);
      try
       MemStream.Write(VAR_META, lengths.VR_META);
       for i:=0 to length(buffers)-1 do
          MemStream.Write(self.buffers[i].b^,self.buffers[i].l^);
       fsOutput.Write(MemStream.GetBuffer(), 0, memoryStream.Position);
      finally
        MemStream.Free;
      end;
    finally
      fsOutput.Free;
    end;
    except
      on E:Exception do
        Writeln(E.Classname, ': ', E.Message);
  end;
end;

1 个答案:

答案 0 :(得分:1)

您的代码显示了一些初学者常见的错误。

  1. 实际上不需要TMemoryStream。正如David所说,这会损害性能。
  2. 将所有内容都写入单个TMemoryStream也不是一个好主意,因为您可能会遇到“内存不足”的问题。
  3. 如果缓冲区的大小确实很小,并且使用内存缓冲区是有好处的,则应该分两个循环执行-内部循环将一定数量的数据写入内存流,而out循环将内存流复制到文件中流并清空内存流。
  4. 不幸的是,Capacity中的TMemoryStream(受保护)是无用的,因为只要更改TMemoryStreamSize就会重新分配内存。使用足够大的TBytes可以避免重新分配内存,但是您需要跟踪长度。
  5. 您为什么只将标头对象写入文件?您打算稍后将正文附加到文件中吗?附加文件通常是个坏主意。
  6. 有些琐碎的事情:总是将string常量与const一起传递。
  7. 有些琐碎的事情:总是以'T'开头的类型名称。

这是我要怎么做:

procedure TDictionary.SaveHeaderToStream(AStream: TStream);
// You want to write to a stream, not a file. This is more reusable.
// You don't want to put the create/free code here,
// this is more flexible as it can also be used by SaveToStream
var
  i: Integer;
begin
  for i := 0 to length(buffers) - 1 do
    AStream.Write(self.buffers[i].b^, self.buffers[i].l^);
end;

procedure TDictionary.SaveHeaderToFile(const Filename: string);
var
  fsOutput: TFileStream;
begin
  fsOutput := TFileStream.Create(Filename, fmCreate);
  try
    SaveHeaderToStream(fsOutput);       // fsOutput IS TStream
  finally
    fsOutput.Free;
  end;
end;

procedure TDictionary.SaveBodyToStream(AStream: TStream);
begin
  // Codes here
end;

procedure TDictionary.SaveToStream(AStream: TStream);
begin
  SaveHeaderToStream(AStream);
  SaveBodyToStream(AStream);
end;

procedure TDictionary.SaveToFile(const Filename: string);
var
  fsOutput: TFileStream;
begin
  fsOutput := TFileStream.Create(Filename, fmCreate);
  try
    SaveToStream(fsOutput);
  finally
    fsOutput.Free;
  end;
end;