Search code examples
c#streambinaryformatter

Trying to create a bin-file using stream


I onced managed to create the bin-file in my project. I changed the primary key from int to Guid and moved code from Main to my class Quote. At the moment I can only add new entries in said file. If I remove it a new file(0 bytes) is created and the stream gets ArgumentException when I try to feed the file dummy-data. I am trying to use an if-loop to handle stream.Lenght == 0.

public static List<Quote> readBinaryToList()        //Crashes if binfile is 0 bytes long
{
    IFormatter formatter = new BinaryFormatter();
    Stream stream = new FileStream(@"C:\Users\xxxxxx\Desktop\quotes.bin", FileMode.OpenOrCreate, FileAccess.Read, FileShare.Read);
    if (stream.Length == 0)
    {
        Quote q = new Quote(Guid.NewGuid(), "Quote dummy", false);
        List<Quote> quoteList = new List<Quote>();
        quoteList.Add(q);
        var bformatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
        bformatter.Serialize(stream, quoteList);

        bformatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
        List<Quote> quoteListTmp = (List<Quote>)bformatter.Deserialize(stream);

        return quoteList;
    }
    else
    {
        List<Quote> quoteList = (List<Quote>)formatter.Deserialize(stream);
        stream.Close();
        return quoteList;
    }
}

Solution

  • As pointed out in previous answers, you must give your file stream write permissions which can be done in its constructor, then you should also set the position of the stream back to 0, you can achieve this by using the stream's Position property.

    You are creating a lot of unnecessary objects that don't actually contribute to purpose of the method I have omitted these below. In doing so, setting the streams Position property to 0 is redundant but I've left it in a comment to show how its done.

    Some other things to consider: Declare the file stream inside a using statement so that it is disposed when the method comes to an end this means you can omit the manual close in the else statement. Some of your code can be written more tersely, this is just a personal preference but I think it would be best to inline some of your code to remove as much noise as possible. It is also convention in C# to use PascalCase for Methods.

    public static List<Quote> ReadBinaryToList(){
      using(Stream stream = new FileStream(@"quotes.bin", FileMode.OpenOrCreate, FileAccess.ReadWrite)) {
           IFormatter formatter = new BinaryFormatter();
    
            if (stream.Length == 0) {
               List<Quote> quoteList = new List<Quote> {new Quote(Guid.NewGuid(), "Quote dummy", false)};
               formatter.Serialize(stream, quoteList);
               //stream.Position = 0;
               return quoteList;
            }
            else return (List<Quote>)formatter.Deserialize(stream);               
       }
    }