View Issue Details

IDProjectCategoryView StatusLast Update
0035330FPCRTLpublic2019-05-13 16:29
Reporterrd0xAssigned ToMichael Van Canneyt 
PrioritynormalSeverityminorReproducibilityalways
Status closedResolutionfixed 
PlatformOSWindows/LinuxOS Version
Product Version3.2.0Product Buildr41756 
Target VersionFixed in Version3.3.1 
Summary0035330: TFileStream.ReadBuffer fails with TBytes while Delphi works
DescriptionfResultBytes: TBytes;

In Delphi
TFileStream.ReadBuffer(fResultBytes, fBytesToEnd);
works fine without issues while in FPC it crashes the program or throws an exception (Stream read error)

In FPC and Delphi
TFileStream.ReadBuffer(fResultBytes[0], fBytesToEnd);
works fine
Steps To Reproducerun the attached program and change the lines for ReadBuffer
Additional Informationhappens also on trunk
TagsNo tags attached.
Fixed in Revision42042
FPCOldBugId
FPCTarget3.2.0
Attached Files
  • filestream.pas (1,667 bytes)
    program filestream;
    
    {$IFDEF FPC}
      {$mode Delphi}
    {$ELSE}
      {$AppType CONSOLE}
    {$ENDIF}
    
    uses
      Classes, SysUtils, Contnrs;
    
    
    function ReadLastLines(const LineCount: Integer; const FN: String): String;
    var
      fStream: TFileStream;
      fLinesRead, fBytesToEnd: Integer;
      c: Byte;
      fResultBytes: TBytes;
    begin
      Result := '';
    
      fStream := TFileStream.Create(FN, fmOpenRead, fmShareDenyNone);
      try
        fLinesRead := 0;
        fStream.Seek(0, soEnd);
        while ((fLinesRead < LineCount) and (fStream.Seek(-2, soCurrent) >= 0)) do
        begin
          fStream.Read(c, SizeOf(c));
          if c = 10 then
          begin
            Inc(fLinesRead);
          end;
        end;
    
        if fLinesRead < LineCount then
        begin
          fStream.Position := 0;
        end;
    
        fBytesToEnd := fStream.Size - fStream.Position;
        SetLength(fResultBytes, fBytesToEnd);
    
        try
          fStream.ReadBuffer(fResultBytes[0], fBytesToEnd); // works fine
    	  //fStream.ReadBuffer(fResultBytes, fBytesToEnd); // error: '[EXCEPTION] ReadBuffer: Stream read error' or program crash
        except
          on e: Exception do
          begin
            writeln(Format('[EXCEPTION] ReadBuffer: %s', [e.Message]));
          end;
        end;
      finally
        fStream.Free;
      end;
    
      Result := TEncoding.UTF8.GetString(fResultBytes);
    end;
    
    
    var
      LastLines: String;
      filename: String;
    
    begin
      filename := ExtractFilePath(ParamStr(0)) + 'x.txt';
      try
        LastLines := ReadLastLines(8, filename);
      except
        on e: Exception do
        begin
          writeln(Format('[EXCEPTION] %s', [e.Message]));
        end;
      end;
      writeln('- output -');
      writeln(LastLines);
    
      readln;
    end.
    filestream.pas (1,667 bytes)
  • x.txt (251 bytes)
    The quick brown fox jumps over the lazy dog
    asdf
    The quick brown fox jumps over the lazy dog
    The quick brown fox jumps over the lazy dog
    lskfsgh
    The quick brown fox jumps over the lazy dog
    The quick brown fox jumps over the lazy dog
    fsgdhfhfh
    
    x.txt (251 bytes)

Activities

rd0x

2019-04-06 11:13

reporter  

filestream.pas (1,667 bytes)
program filestream;

{$IFDEF FPC}
  {$mode Delphi}
{$ELSE}
  {$AppType CONSOLE}
{$ENDIF}

uses
  Classes, SysUtils, Contnrs;


function ReadLastLines(const LineCount: Integer; const FN: String): String;
var
  fStream: TFileStream;
  fLinesRead, fBytesToEnd: Integer;
  c: Byte;
  fResultBytes: TBytes;
begin
  Result := '';

  fStream := TFileStream.Create(FN, fmOpenRead, fmShareDenyNone);
  try
    fLinesRead := 0;
    fStream.Seek(0, soEnd);
    while ((fLinesRead < LineCount) and (fStream.Seek(-2, soCurrent) >= 0)) do
    begin
      fStream.Read(c, SizeOf(c));
      if c = 10 then
      begin
        Inc(fLinesRead);
      end;
    end;

    if fLinesRead < LineCount then
    begin
      fStream.Position := 0;
    end;

    fBytesToEnd := fStream.Size - fStream.Position;
    SetLength(fResultBytes, fBytesToEnd);

    try
      fStream.ReadBuffer(fResultBytes[0], fBytesToEnd); // works fine
	  //fStream.ReadBuffer(fResultBytes, fBytesToEnd); // error: '[EXCEPTION] ReadBuffer: Stream read error' or program crash
    except
      on e: Exception do
      begin
        writeln(Format('[EXCEPTION] ReadBuffer: %s', [e.Message]));
      end;
    end;
  finally
    fStream.Free;
  end;

  Result := TEncoding.UTF8.GetString(fResultBytes);
end;


var
  LastLines: String;
  filename: String;

begin
  filename := ExtractFilePath(ParamStr(0)) + 'x.txt';
  try
    LastLines := ReadLastLines(8, filename);
  except
    on e: Exception do
    begin
      writeln(Format('[EXCEPTION] %s', [e.Message]));
    end;
  end;
  writeln('- output -');
  writeln(LastLines);

  readln;
end.
filestream.pas (1,667 bytes)

rd0x

2019-04-06 11:14

reporter  

x.txt (251 bytes)
The quick brown fox jumps over the lazy dog
asdf
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy dog
lskfsgh
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy dog
fsgdhfhfh
x.txt (251 bytes)

Michael Van Canneyt

2019-04-06 11:25

administrator   ~0115262

This is a known issue.

Delphi has a special overload for TBytes. FPC does not have this.
I will add it, but for the time being, you must use the fResultBytes[0] variant.

Marco van de Voort

2019-04-18 14:54

manager   ~0115648

TFilestream or TStream?

Michael Van Canneyt

2019-05-12 12:10

administrator   ~0116146

Added Read/Write for TBytes.

Also Added ReadData/WriteData ReadBufferData/WriteBufferDate methods found in newer delphis.

Issue History

Date Modified Username Field Change
2019-04-06 11:13 rd0x New Issue
2019-04-06 11:13 rd0x File Added: filestream.pas
2019-04-06 11:14 rd0x File Added: x.txt
2019-04-06 11:24 Michael Van Canneyt Assigned To => Michael Van Canneyt
2019-04-06 11:24 Michael Van Canneyt Status new => assigned
2019-04-06 11:25 Michael Van Canneyt Note Added: 0115262
2019-04-18 14:54 Marco van de Voort Note Added: 0115648
2019-05-12 12:10 Michael Van Canneyt Status assigned => resolved
2019-05-12 12:10 Michael Van Canneyt Resolution open => fixed
2019-05-12 12:10 Michael Van Canneyt Fixed in Version => 3.3.1
2019-05-12 12:10 Michael Van Canneyt Fixed in Revision => 42042
2019-05-12 12:10 Michael Van Canneyt FPCTarget => 3.2.0
2019-05-12 12:10 Michael Van Canneyt Note Added: 0116146
2019-05-13 16:29 rd0x Status resolved => closed