John Boe
John Boe

Reputation: 3621

how to convert memorystream to filestream in Delphi 7?

I have this code, where I am reading buffers to memory stream and I want to save it to file stream. The problem is that memoryStream.GetBuffer() does not work for my Delphi 7 as it is undeclared identifier.

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;

Upvotes: 0

Views: 4081

Answers (1)

W. Chang
W. Chang

Reputation: 502

Your code showed several mistakes common to beginners.

  1. There really is no need for the TMemoryStream. As David said, it hurts performance.
  2. It's also not a good idea to write everything to a single TMemoryStream, because you may ran into "Out of memory" problem.
  3. If the buffer size is really small and using a memory buffer is beneficial, you should do it in two loops - the inner loop writes a certain number of data to the memory stream and the out loop copies the memory stream to the file stream and empty the memory stream.
  4. Unfortunately Capacity (protected) of TMemoryStream is useless because TMemoryStream reallocates memory whenever Size is changed. Using a sufficiently big TBytes avoids memory reallocation but you need to keep track of the length.
  5. Why did you just write the header object to the file? Do you intend to append the body to the file later? Append a file is usually a bad idea.
  6. Some thing trivial: always pass string constants with const.
  7. Some thing trivial: always start a type name with 'T'.

Here is how I would do it:

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;

Upvotes: 2

Related Questions