二进制Writer / Reader额外字符

时间:2015-07-08 01:29:48

标签: c# vb6 binaryreader binarywriter

我正在将一些传统的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中没有终止,这也是四个字节,而不仅仅是一个额外的字节?那么额外的4个字节来自哪里呢?我不是直接调用Write(字符串)所以它不能是一个前缀长度,它显然不是因为它在我的字符串之后。如果取消注释ReadInt32(),它将产生所需的结果。

2 个答案:

答案 0 :(得分:2)

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

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

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

答案 1 :(得分:0)

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

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

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

例如,假设您有一个120字节的文件。该文件的前4个字节表示以下字符串的长度为96个字节。所以你读取4个字节,得到长度,然后读取96个字节。接下来的4个字节表示你有一个16字节长的字符串,所以你读取接下来的16个字节并得到你的下一个字符串。这几乎就是每个定义良好的协议的工作原理。