调用FileRead后的Strange Count值

时间:2018-01-04 18:24:38

标签: windows delphi winapi delphi-10-seattle

我正在尝试将读取的字节数与传递给FileRead的计数进行比较,ReadFile是WinAPi enter image description here函数的包装。

问题是我根据ReadFromFile过程的结构得到了不同的值(没有添加/减去的行改变计数变量)。

如果您运行以下代码,则会获得此输出

FileHandle: 400
SizeOfFile: 8672
Current position: 8655
aCount before SetLength: 17
aCount before FileRead: 17
Number of bytes read: 17
aCount after FileRead: 2200
EAccessViolation: Access violation at address 0040C5BC in module 'Project7.exe'. Read of address C23C30BA

AV是因为编译器在范围结束时释放了动态数组(这并不总是如此)。 你可以在FileRead之后看到count == 2200这里(我之前得到0)。如果您注释掉第二个API调用或第二行,那么计数是正确的

你能告诉我这是什么以及如何解决它?

program Project7;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils, WinAPI.Windows, System.Classes;


procedure ReadFromFile(aFileHandle: THandle; aCount: Longint);
var
  aPosition, ReadRes: Int64;
  TmpBuffer: TBytes;
begin
  writeln('aCount before SetLength: ',aCount);
  SetLength(TmpBuffer, aCount);
  writeln('aCount before FileRead: ',aCount);
  ReadRes := FileRead(aFileHandle, TmpBuffer, aCount);
  Writeln('Number of bytes read: ', ReadRes);
  //aPosition := FileSeek(aFileHandle, 0, Ord(soCurrent)); // second API call
  //Writeln('Current position after read: ', aPosition);  // line two
  writeln('aCount after FileRead: ',aCount);
  if ReadRes <> aCount then
    //Raise Exception.Create('hi there');
 // DoWrite(TmpBuffer[0], aCount);
end;

var
  FFileHandle: THandle;
  aFileName: string;
  I1: Integer;
  aFilePhysicalSize: Int64;
  FPosition: Int64;
begin
  try
    aFileName := 'C:\Users\nacereddine\Desktop\ascii-table.gif';
    { TODO -oUser -cConsole Main : Insert code here }
    FFileHandle := CreateFile(PChar(aFileName), GENERIC_READ,
                                FILE_SHARE_READ, nil, OPEN_EXISTING,
                                FILE_ATTRIBUTE_NORMAL, 0);
    Writeln('FileHandle: ', FFileHandle);
    aFilePhysicalSize := FileSeek(FFileHandle, 0 , Ord(soEnd));
    Writeln('SizeOfFile: ', aFilePhysicalSize);
    FPosition := FileSeek(FFileHandle, aFilePhysicalSize - 17 , Ord(soBeginning));
    Writeln('Current position: ', FPosition);
    I1 := 17;
    ReadFromFile(FFileHandle, I1);

    readln;

  except

    on E: Exception do
    begin
    Writeln(E.ClassName, ': ', E.Message);
    readln;
    end;
  end;
end.

1 个答案:

答案 0 :(得分:3)

您正在使用带有无类型第二个参数的过程fileread的版本:

TmpBuffer: TBytes;
...
ReadRes := FileRead(aFileHandle, TmpBuffer, aCount);

但在这种情况下,您应该取消引用动态数组,例如TmpBuffer[0]

从您的帮助链接:

 //this version is used
 function FileRead(Handle: THandle; var Buffer; Count: LongWord): Integer;
 //perhaps you wanted that one:
 function FileRead(Handle: THandle; var Buffer: TBytes; Offset, Count: LongWord): Integer;