-1

我正在将一些遗留的 VB6 代码转换为 C#,这让我有点困惑。VB6 代码将某些数据顺序写入文件。该数据始终为 110 字节。我可以在转换后的代码中很好地读取这个文件,但是当我从转换后的代码编写文件时遇到了问题。

这是我在 LINQPad 中快速编写的精简示例:

void Main()
{
  int[,] data = new[,]
  {
    {
      0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19
    },
    {
      20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39
    }
  };

  using ( MemoryStream stream = new MemoryStream() )
  {
    using ( BinaryWriter writer = new BinaryWriter( stream, Encoding.ASCII, true ) )
    {
      for( var i = 0; i < 2; i++ )
      {
        byte[] name = Encoding.ASCII.GetBytes( "Blah" + i.ToString().PadRight( 30, ' ' ) );

        writer.Write( name );
        for( var x = 0; x < 20; x++ )
        {
          writer.Write( data[i,x] );
        }
      }
    }

    using ( BinaryReader reader = new BinaryReader( stream ) )
    {
      // Note the extra +4 is because of the problem below.
      reader.BaseStream.Seek( 30 + ( 20 * 4 ) + 4, SeekOrigin.Begin );

      string name = new string( reader.ReadChars(30) );
      Console.WriteLine( name );

      // This is the problem..This extra 4 bytes should not be here.
      //reader.ReadInt32();

      for( var x = 0; x < 20; x++ )
      {
        Console.WriteLine( reader.ReadInt32() );
      }
    }
  }
}

如您所见,我首先编写了一个 30 个字符的字符串。该字符串永远不会超过 30 个字符,如果它更短,则用空格填充。之后,写入 20 个 32 位整数。它始终是 20 个整数。所以我知道字符串中的每个字符都是一个字节。我知道一个 32 位整数是四个字节。所以在我的阅读器示例中,我应该能够查找 110 个字节( 30 + (4 * 20) ),读取 30 个字符,然后读取 20 个整数,这就是我的数据。但是,由于某种原因,在字符串之后写入了额外的 4 个字节。

我是否只是遗漏了一些完全明显的东西(通常是我自己的情况)?字符串在 .Net 中不是以 null 结尾的,无论如何这是四个字节,而不仅仅是一个额外的字节?那么这额外的 4 个字节是从哪里来的呢?我没有直接调用 Write(string) 所以它不能是前缀长度,这显然不是因为它在我的字符串之后。如果取消注释 ReadInt32(),它将产生所需的结果。

4

2 回答 2

2

额外的 4 个字节来自您正在编写的额外 4 个字符。将您编码为 ASCII 的字符串更改为:

("Blah" + i.ToString()).PadRight(30, ' ')

也就是说,在连接前缀和整数之后填充字符串。

于 2015-07-08T02:04:26.467 回答
0

您额外的四个字节是空格,因为您没有减去“Blah”的长度。您不知道自己在信息流中的位置。所以基本上,你认为你只写了 30 个字符,但你真的写了 34 个字符。

我知道你没有问这个 - 但你正在将垃圾数据写入一个不需要存在的文件中。

您应该只包含一个标头或指针,指示文件中下一个字段的长度,而不是用空格填充您的字符串。

例如,假设您有一个 120 字节的文件。文件的前 4 个字节表示后面的字符串长度为 96 个字节。因此,您读取 4 个字节,获取长度,然后读取 96 个字节。接下来的 4 个字节表示您有一个 16 字节长的字符串,因此您读取接下来的 16 个字节并获取下一个字符串。这几乎就是每个定义良好的协议的工作方式。

于 2015-07-08T03:08:50.473 回答