Delphi’s TStream.Read returns the number of bytes read

Note to self: TStream.Read in the Delphi RTL returns the number of bytes read. It does not check whether the intended number of bytes could actually be read. So if you do not check it yourself, call TStream.ReadBuffer instead.

So, it’s either:

var
  st: TFileStream;
  Buffer: array[0..7] of Byte;
  BytesRead: Integer;
begin
  st := TFileStream.Create(fn, fmOpenRead);
  try
    BytesRead := st.Read(Buffer, SizeOf(Buffer));
    if BytesRead <> SizeOf(Buffer) then
      raise Exception.CreateFmt('BytesRead (%d) <> SizeOf(Buffer) (%d)',
        [BytesRead, SizeOf(Buffer)]);
    // do something with the content of buffer
  finally
    FreeAndNil(st);
  end;
end;

or

var
  st: TFileStream;
  Buffer: array[0..7] of Byte;
begin
  st := TFileStream.Create(fn, fmOpenRead);
  try
    st.ReadBuffer(Buffer, SizeOf(Buffer));
    // do something with the content of buffer
  finally
    FreeAndNil(st);
  end;
end;

The same logic applies to TStream.Write and TStream.WriteBuffer.

I have just grep-ed my sources and found way to many places where I used Read instead of ReadBuffer and Write instead of WriteBuffer.

Unfortunately that’s an easy mistake to make, so I guessed that I am not the only one who made it. And lo and behold, I found lots of places in the Delphi 2007 RTL and VCL (so they might have been fixed in the mean time, I didn’t check though) and several 3rd party libraries (including the current JCL and JVCL) where this mistake was made. So it’s probably a good idea if you do that check on your own code.

The regular expressions I used for this were:

^\s*\w*\.read\(
^\s*\w*\.write\(

If you use GExperts Grep, don’t forget to enable the “Regular Expression” option!