0

我的 win32 程序创建了一个二进制文件,其后只有一个字符串 [32] 和一个整数。然后,我编写了一个 .NET 程序来读取同一个文件。

这是我的 .NET 代码:

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;

它可能无法读取文件。实际上,它引发了“读取超出文件末尾”异常。原因是字符串长度正好是 32 个字符。我相信 BinaryReader 没有这些信息。因此,它读取的字符串超过 32 个字符。因此,它无法正确读取二进制文件。

那么,在这种情况下,如何读取 .NET 框架下的二进制 win32 文件呢?

更新

这是我的 .NET 更新代码:

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;

虽然这可行,但我似乎无法从 tmparray 中检索字符串。FHeader.id 是字符串类型。ToString 似乎无法正常工作。在这行代码之后,FHeader.id 等于“System.Char[]”。它实际上并不包含字符串本身。

任何的想法?

提前致谢,

4

3 回答 3

2

正如ReadString 的文档中所解释的,它期望字符串“以长度为前缀,一次编码为一个整数七位”。(这有点不清楚,但我猜大多数人会阅读他们使用 编写的字符串BinaryWriter.Write(String))。

如果您有一个已知长度的字符串(例如在这种情况下为 32)或想要读取整个文件,您可能应该使用其中一个BinaryReader.Read重载

更新问题的答案

char[].ToString()不会将字符连接成字符串。相反,它将给出一个字符数组 ( "System.Char[]") 的描述性表示。

您可以做的是使用string构造函数将 转换char[]为等效字符串。看到这个答案

更新:正如另一个答案和评论所提到的,您应该在将 转换为 时注意正确的char[]编码string。构造String(Char[])函数假定 unicode characters,这可能是也可能不是您需要的(尽管它适用于纯 ASCII)

于 2012-04-27T13:31:31.977 回答
1

BinaryReader.ReadString() 只能读取由 BinaryReader.WriteString() 写入的字符串。文件中的字符串数据以一个可变长度字段为前缀,该字段存储字符串长度。

解决方法很简单,您只需调用 ReadBytes(32) 即可。然后使用 Encoding.GetString() 将字节转换为字符串。

不那么简单的是选择正确的 Encoding 类。它需要与编写文件的程序中使用的编码相匹配。这是一个丑陋的实现细节,可能会让您在处理在世界其他地方编写的文件时遇到麻烦。Encoding.Default 将在文件没有传播很远时起作用。

于 2012-04-27T14:19:06.777 回答
1

您将 Delphi 存储ShortString到文件中。A开头ShortString包含 a以指定. 在您的 .NET 代码中,您需要读取 a ,然后读取指定数量的 8 位字符,然后读取 4 字节整数,例如:ByteAnsiCharShortStringByte

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;
于 2012-04-27T20:17:10.620 回答