2014-01-07 88 views
3

我解析MNIST数据集在C#中的:http://yann.lecun.com/exdb/mnist/我在C#中用BinaryReader解析MNIST数据集有什么问题?

我试图读取二进制文件的第一Int32

FileStream fileS = new FileStream(fileName, FileMode.Open, FileAccess.Read); 
BinaryReader reader = new BinaryReader(fileS); 
int magicNumber = reader.ReadInt32(); 

但是,它给了我一个无感号码:50855936 。

如果我使用File.ReadAllBytes()

buffer = File.ReadAllBytes(fileName); 

然后通过字节看,它工作正常(的前四个字节现在代表2049年),我在BinaryReader上做了什么错误?

文件格式如下(我想读第一幻数):

All the integers in the files are stored in the MSB first (high endian) format used by most non-Intel processors. Users of Intel processors and other low-endian machines must flip the bytes of the header. 

训练集标签文件(列车标签-IDX1-UBYTE):

[offset] [type]   [value]   [description] 
0000  32 bit integer 0x00000801(2049) magic number (MSB first) 
0004  32 bit integer 60000   number of items 
0008  unsignebyte  ??    label 
0009  unsigned byte ??    label 
........ 
xxxx  unsigned byte ??    label 
The labels values are 0 to 9.d 
+0

你的文件是什么编码?默认情况下,BinaryReader使用UTF-8。 尝试在BinaryReader构造器调用中指定它,如果它不同于UTF-8。 – nestedloop

+0

你能举一个你认为是错误的例子吗? –

+0

endiannes问题? –

回答

7

50855936 == 0x03080000。或者0x00000803当你翻转字节时,几乎所有的机器都需要它,因为little-endian已经赢得了蛋战。足够接近2049,没有伟大的想法。2.是什么因素造成的偏移这里有一个扩展的方法来帮助你看懂了:

public static class BigEndianUtils { 
     public static int ReadBigInt32(this BinaryReader br) { 
      var bytes = br.ReadBytes(sizeof(Int32)); 
      if (BitConverter.IsLittleEndian) Array.Reverse(bytes); 
      return BitConverter.ToInt32(bytes, 0); 
     } 
    } 

添加额外的方法,如果文件中包含多个字段类型,刚刚替补的Int32的片段。

+0

0x03080000值可能是由于一些其他错误(OP可能只是错误输入号码)。如果您使用BinaryWriter编写2049值,它会按预期使用little-endian生成0x01080000。 – Luaan

+0

对于后验性 - OP是在C#(http://yann.lecun.com/exdb/mnist/)和** 0x00000803 **(2051)和** 0x00000801 **(2049)差异中解析** MNIST **数据库是由于错误复制从提到的网站。 2049代表** train-labels-idx1-ubyte **数据集的“幻数”,2051代表MNIST的** train-images-idx3-ubyte **数据集的“幻数”。 – mwilczynski

0

看来你的问题在别的地方。你能发布一个不能按预期工作的最小可编译代码片段吗?

例如,这段代码完全按照预期工作 - 它创建了一个8字节的二进制文件,它是两个大端Int32。读者然后正确地读取数据作为两个整数。

using (var str = File.Create("C:\\Test.dat")) 
    using (var wr = new BinaryWriter(str)) 
    { 
     wr.Write(2049); 
     wr.Write(60000); 
    } 

using (var str = File.Open("C:\\Test.dat", FileMode.Open)) 
    using (var rdr = new BinaryReader(str)) 
    { 
     rdr.ReadInt32().Dump(); 
     rdr.ReadInt32().Dump(); 
    } 

但是,字节顺序是固定的。如果您需要先使用MSB,则需要读取字节并将它们自己转换为整数(或者,当然,如果您愿意,可以使用按位运算来反转字节顺序)。