Search code examples
c#readfileeof

How to read binary files until EOF in C#


I have a function to write some data into a binary file

private void writeToBinFile (List<MyClass> myObjList, string filePath)
{
    FileStream fs = new FileStream(filePath, FileMode.Create);
    BinaryWriter bw = new BinaryWriter(fs);

    foreach (MyClass myObj in myObjList)
    {
        bw.Write(JsonConvert.SerializeObject(myObj));
    }
    bw.Close();
    fs.Close();

}

I am looking something like

FileStream fs = new FileStream(filePath, FileMode.Create);
BinaryReader bw = new BinaryReader(fs);

while (!filePath.EOF)
{
    List<MyClass> myObjList = br.Read(myFile);
}

anyone can help with this? thanks in advance


Solution

  • JSON can be saved with no formatting (no new lines), so you can save 1 record per row of a file. Thus, my suggested solution is to ignore binary files and instead use a regular StreamWriter:

    private void WriteToFile(List<MyClass> myObjList, string filePath)
    {
        using (StreamWriter sw = File.CreateText(filePath))
        {
            foreach (MyClass myObj in myObjList)
            {
                sw.Write(JsonConvert.SerializeObject(myObj, Newtonsoft.Json.Formatting.None));
            }
        }
    }
    
    private List<MyClass> ReadFromFile(string filePath)
    {
        List<MyClass> myObjList = new List<MyClass>();
        using (StreamReader sr = File.OpenText(filePath))
        {
            string line = null;
            while ((line = sr.ReadLine()) != null)
            {
                myObjList.Add(JsonConvert.DeserializeObject<MyClass>(line));
            }
        }
        return myObjList;
    }
    

    If you really want to use the binary writer to save JSON, you could change it to be like this:

    private void WriteToBinFile(List<MyClass> myObjList, string filePath)
    {
        using (FileStream fs = new FileStream(filePath, FileMode.Create))
        using (BinaryWriter bw = new BinaryWriter(fs))
        {
            foreach (MyClass myObj in myObjList)
            {
                bw.Write(JsonConvert.SerializeObject(myObj));
            }
        }
    }
    
    private List<MyClass> ReadFromBinFile(string filePath)
    {
        List<MyClass> myObjList = new List<MyClass>();
        using (FileStream fs = new FileStream(filePath, FileAccess.Read))
        using (BinaryReader br = new BinaryReader(fs))
        {
            while (fs.Length != fs.Position) // This will throw an exception for non-seekable streams (stream.CanSeek == false), but filestreams are seekable so it's OK here
            {
                myObjList.Add(JsonConvert.DeserializeObject<MyClass>(br.ReadString()));
            }
        }
        return myObjList;
    }
    

    Notes:

    • I've added using around your stream instantiations so that the files are properly closed when memory is freed
    • To check the stream is at the end, you have to compare Length to Position.