Tiny
Tiny

Reputation: 419

Reading binary file data into List of Structs

I have a simple procedure to write a list of library books (of type TBook) to a binary file as follows:

static void SaveToFile(List<TBook> lib)
    {
        FileStream currentFile;
        BinaryWriter writerToFile;
        currentFile = new FileStream("MyLibrary.bin", FileMode.Create);
        writerToFile = new BinaryWriter(currentFile);
        foreach (TBook book in lib)
        {
            writerToFile.Write(book.Title);
            writerToFile.Write(book.Author);
            writerToFile.Write(book.Genre);
            writerToFile.Write(book.BookID);
        }
        writerToFile.Close();
        currentFile.Close();
    }

However, when trying to read the binary file and load contents into a list, i get an error:

An unhandled exception of type 'System.IO.EndOfStreamException' occurred in mscorlib.dll

Additional information: Unable to read beyond the end of the stream.

Here is my subroutine that attempts to read the Binary File back into a Struct again:

static List<TBook> LoadDataFromFile (List<TBook>library)
    {
        FileStream currentFile;
        BinaryReader readerFromFile;
        currentFile = new FileStream("MyLibrary.bin", FileMode.Open);
        readerFromFile= new BinaryReader(currentFile);

        while (currentFile.Position < currentFile.Length)
        {
            TBook CurrentRecord = new TBook();
            CurrentRecord.Title = readerFromFile.ReadString();
            CurrentRecord.Author = readerFromFile.ReadString();
            CurrentRecord.Genre = readerFromFile.ReadString();
            CurrentRecord.BookID = readerFromFile.ReadInt16();
            library.Add(CurrentRecord);                
       }

        readerFromFile.Close();
        currentFile.Close();
        return library;
    }

I assume the issue is with the line:

while (currentFile.Position < currentFile.Length) 

Note: The Struct is setup as follows:

struct TBook
    {
        public string Title;
        public string Author;
        public string Genre;
        public int BookID;
    }

Upvotes: 1

Views: 456

Answers (1)

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726987

When you are serializing data as binary, your deserialization code must follow serialization code exactly; otherwise your deserializer starts reading junk from adjacent positions, eventually causing an exception or silently populating your structures with wrong data.

This pair of calls is mismatched:

writerToFile.Write(book.BookID);
....
CurrentRecord.BookID = readerFromFile.ReadInt16();

It is hard to see this problem, because BinaryWriter overloads the Write method. Since book.BookID is of type int, an alias for Int32, the call to Write is resolved to Write(Int32). Therefore, the corresponding read must also read Int32, not Int16:

CurrentRecord.BookID = readerFromFile.ReadInt32();

Upvotes: 1

Related Questions