Search code examples
.netstringwinapibinaryfilesdelphi-prism

How to read n characters from a binary file created under win32 with .NET?


My win32 program created a binary file with only a string[32] and an integer right after it. Then, I wrote a .NET program to read that same file.

Here is my .NET code:

method ReadUnitFile;
var
  FHeader:TFileHeader;
  Biread:BinaryReader;
  FUnitLoc:String;
begin
  FUnitLoc := baseDir+'\system\Units.dat';
  if Environment.OSVersion.Platform = System.PlatformID.Unix then
    FUnitLoc := baseDir+'/system/Units.dat';

  if File.Exists(FUnitLoc) then
  begin
    Biread:= new BinaryReader(File.OpenRead(FUnitLoc));

    FHeader.id:=Biread.ReadString;
    FHeader.version:=Biread.ReadInt32;
    Biread.Close;
  end;
end;

It failed to read the file probably. In fact, it raised "read beyond end of file" exception. The reason for that is because the string is exactly 32 characters long. I believe that the BinaryReader doesn't have the information. So, it reads beyond 32 characters for the string. Thus, it fails to read the binary file properly.

So, how do you read a binary-win32-file under .NET framework in this case?

UPDATE

Here is my .NET updated code:

method ReadUnitFile;
var
  FHeader:TFileHeader;
  Biread:BinaryReader;
  FUnitLoc:String;
  tmparray:array[0..32] of char;
begin
  FUnitLoc := baseDir+'\system\Units.dat';
  if Environment.OSVersion.Platform = System.PlatformID.Unix then
    FUnitLoc := baseDir+'/system/Units.dat';

  if File.Exists(FUnitLoc) then
  begin
    Biread:= new BinaryReader(File.OpenRead(FUnitLoc));

    Biread.Read(tmparray,0,32);
    FHeader.id := tmparray.ToString;
    FHeader.version:=Biread.ReadInt32;
    Biread.Close;
  end;
end;

Although this works, I can't seem to retrieve the string from tmparray. FHeader.id is a string type. ToString doesn't seem to be working right. After that line of code, FHeader.id is equals "System.Char[]." It doesn't actually contain the string itself.

Any idea?

Thanks in advance,


Solution

  • You stored a Delphi ShortString into the file. A ShortString contains a Byte at the beginning to specify how many AnsiChar elements are in the ShortString. In your .NET code, you need to read a Byte, then read the specified number of 8-bit characters, then read a 4-byte integer, eg:

    method ReadUnitFile;
    var
      FHeader: TFileHeader;
      Biread: BinaryReader;
      FUnitLoc: String;
    begin
      FUnitLoc := baseDir+'\system\Units.dat';
      if Environment.OSVersion.Platform = System.PlatformID.Unix then
        FUnitLoc := baseDir+'/system/Units.dat';
      if File.Exists(FUnitLoc) then
      begin
        Biread := new BinaryReader(File.OpenRead(FUnitLoc));
        FHeader.id := System.Encoding.Default.GetString(Biread.ReadBytes(Biread.ReadByte));
        FHeader.version := Biread.ReadInt32;
        Biread.Close;
      end;
    end;