Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What did I do wrong with parsing MNIST dataset with BinaryReader in C#?

I'm parsing MNIST datasets in C# from: http://yann.lecun.com/exdb/mnist/

I'm trying to read the first Int32 from a binary file:

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

However, it gives me a non-sense number: 50855936.

If I use File.ReadAllBytes()

buffer = File.ReadAllBytes(fileName);

and then look through the bytes, it works fine(the first four bytes now represents 2049), what did I do wrong with BinaryReader?

The file format is as follows (I'm trying to read the first magic number):

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.

TRAINING SET LABEL FILE (train-labels-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 
like image 406
cloudyFan Avatar asked Feb 15 '23 05:02

cloudyFan


1 Answers

50855936 == 0x03080000. Or 0x00000803 when you reverse the bytes, required on almost any machine since little-endian has won the egg war. Close enough to 2049, no great idea what explains the offset of 2. Here's an extension method to help you read it:

  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);
      }
  }

Add additional methods if the file contains more field types, just substitute Int32 in the snippet.

like image 121
Hans Passant Avatar answered May 01 '23 22:05

Hans Passant