将二进制读取函数从C#转换为C

时间:2011-04-19 04:40:21

标签: c# c binary-data

老实说,我真的很困惑在阅读C中的二进制文件。

我的数据格式如下:

  • int header
  • Cell [] []细胞,8x8矩阵
  • 每个单元格只是一个简短的id和一个sbyte z。

然而,有些事情显然正在搞乱,而且没有一个值是准确的。

  int i, j;
  Block block;

  // read 32 bits
  fread( &(block.header), sizeof( int ), 1, mapFile );

  // loop through to fill the 8x8 matrix
  for( i = 0; i < 8; i++ )
  {
    for( j = 0; j < 8; j++ )
    {
      // read 16 bits
      fread( &(block.cells[i][j].tileId), sizeof( short ), 1, mapFile );
      // read 8 bits
      fread( &(block.cells[i][j].z), sizeof( char ), 1, mapFile );

      printf( "[%i][%i]: %x %i", i, j, block.cells[i][j].tileId, block.cells[i][j].z );
    }
  }
  printf( "header: %i", block.header );

上面的输出显示了一堆带[n][n]: ffffa800 251的行。

我的C#版本可以正常工作:

            Block block;
            block.header = reader.ReadInt32();
            block.cells = new Cell[8,8];
            for( int i = 0; i < 8; i++ )
            {
                for ( int j = 0; j < 8; j++ )
                {
                    block.cells[i, j].tileId = reader.ReadInt16();
                    block.cells[i, j].z = reader.ReadSByte();
                }
            }

            reader.Close();

来自(正确)的输出显示[n][n]: a8 -5

4 个答案:

答案 0 :(得分:1)

您应该在C中使用更严格定义的类型。例如,int32_t(stdint.h)。您的short可能是32位(甚至您的int是16位),尽管不太可能。

向我们展示如何定义Block struct可能也是值得的。

供参考:

SByte = int8_t

Int16 = int16_t

Int32 = int32_t

答案 1 :(得分:1)

这很可能与short并不总是保证为两个字节的事实有关。也许最好读取指定的字节数然后将其转换为所需的数据类型?这也适用于int。顺便说一句:fread返回读取的字节数,因此您可以检查是否实际读取了所需的字节数。

问候,佩里

答案 2 :(得分:1)

我相信您可能正在使用C#编写文件(BinaryWriter)和C来读取它。因此,文件可能在开头有一些意外的值(一些标题,长度,BOM无论如何)。使用十六进制编辑器确保。

答案 3 :(得分:0)

在C中,变量默认初始化为未定义状态,因此在显式初始化它们之前,不能依赖它们的内容。请记住分配所需的所有内存,并在使用之前将内容清零(初始化)。

例如:memset(&block, '\0', sizeof block);