Unity 5 C# script to write to a binary data file- getting a null reference exception and a IOException: sharing violation

Hoping for some help here – pulled enough hair I am crying “Uncle”

I keep getting two errors; neither of which I seem to be able to resolve myself.

First is a warning about a Null Reference Exception error on the fourth line under ToBinaryDataFile() (“gsaver.NumberPlayers = dataManager.Load(“NUMBEROFPLAYERSPLAYING”).ToString();”). Screenshot by Lightshot. I also get a IOException:Sharing violation Screenshot by Lightshot.

A file is created, but it appears to be of zero length and have nothing inside.

I know all the routines function with the exception of ToBinaryDataFile() and FromBinaryDataFile().

I left the others included mostly as an aide to others that might like to see how I did those (and in case they have some impact somehow).

using UnityEngine;
using System.Collections;
using System;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;

[Serializable]
public class GameInformation : MonoBehaviour
{
    public static string NumberPlayers { get; set; }
    public static string CurrentPlayer { get; set; }
    public static string CurrentPlayerPhase { get; set; }

    void Awake()
    {
        DontDestroyOnLoad(transform.gameObject);
    }
}

// Added the class below as I could not seem to get the static version above to work;  so for purposes of writing to a file I use this redundent non-static class.
[Serializable]
public class SGameInformation
{
    public string NumberPlayers;
    public string CurrentPlayer;
    public string CurrentPlayerPhase;
}

public class SaveInformation
{
    public static void ToPreferences()
    {
        PlayerPrefs.SetString("NUMBEROFPLAYERSPLAYING", GameInformation.NumberPlayers);
        PlayerPrefs.SetString("CURRENTPLAYER", GameInformation.CurrentPlayer);
        PlayerPrefs.SetString("CURRENTPLAYERPHASE", GameInformation.CurrentPlayerPhase);
    }

    public static void ToBinaryDataFile()
    {
        BinaryFormatter binary = new BinaryFormatter();
        FileStream fStream = File.Create(Application.persistentDataPath + "/saveFile.hag");
        SGameInformation gsaver = new SGameInformation() as SGameInformation;
        gsaver.NumberPlayers = dataManager.Load("NUMBEROFPLAYERSPLAYING").ToString();
        gsaver.CurrentPlayer = dataManager.Load("CURRENTPLAYER").ToString();
        gsaver.CurrentPlayerPhase = dataManager.Load("CURRENTPLAYERPHASE").ToString();

        //Tried with and without the following line -- another thread suggested it.
        //Environment.SetEnvironmentVariable("MONO_REFLECTION_SERIALIZER", "yes");
        binary.Serialize(fStream, gsaver);
        fStream.Close();
    }
}

public class LoadInformation
{
    public static void FromPreferences()
    {
        GameInformation.NumberPlayers = PlayerPrefs.GetString("NUMBEROFPLAYERSPLAYING", "Two");
        GameInformation.CurrentPlayer = PlayerPrefs.GetString("CURRENTPLAYER", "1");
        GameInformation.CurrentPlayer = PlayerPrefs.GetString("CURRENTPLAYERPHASE", "1");
    }

    public static void FromBinaryDataFile()
    {
        if (File.Exists(Application.persistentDataPath + "/saveFile.hag"))
        {
            BinaryFormatter binary = new BinaryFormatter();
            FileStream fStream = File.Open(Application.persistentDataPath + "/saveFile.hag", FileMode.Open);
            var gloader = (SGameInformation)binary.Deserialize(fStream) as SGameInformation;
            fStream.Close();

            dataManager.Save("NUMBEROFPLAYINGSPLAYING",gloader.NumberPlayers);
            dataManager.Save("CURRENTPLAYER", gloader.CurrentPlayer);
            dataManager.Save("CURRENTPLAYERPHASE", gloader.CurrentPlayerPhase);
        }
    }
}

    public class dataManager
{
    public static BinaryFormatter binaryFormatter = new BinaryFormatter();

    public static void Save (string saveTag, object obj)
    {
        MemoryStream memoryStream = new MemoryStream();
        binaryFormatter.Serialize(memoryStream, obj);
        string temp = System.Convert.ToBase64String(memoryStream.ToArray());
        PlayerPrefs.SetString(saveTag, temp);
    }

    public static object Load(string saveTag)
    {
        string temp = PlayerPrefs.GetString(saveTag);
        if (temp == string.Empty)
        {
            return null;
        }
        MemoryStream memoryStream = new MemoryStream(System.Convert.FromBase64String(temp));
        return binaryFormatter.Deserialize(memoryStream);
    }
}

Would appreciate responses that resolve the above code. I like how I have it organized – if only it worked(!).

@Bonfire Boy Thank you, I am new to both C# and Unity so appreciate such tips; I’ll try to incorporate that in the future. Here is the solution I came up with (avoided dataManager() as it was throwing back nulls. Didn’t really need it (and don’t really understand it I suspect).

public class SaveInformation
{
    public static void ToGameInformation(string saveTag, object obj)
    {
        switch (saveTag)
        {
            case "NUMBEROFPLAYERSPLAYING":
                GameInformation.NumberPlayers = (string)obj;
                PlayerPrefs.SetString("NUMBEROFPLAYERSPLAYING", GameInformation.NumberPlayers);
                break;
            case "CURRENTPLAYER":
                GameInformation.CurrentPlayer = (string)obj;
                PlayerPrefs.SetString("CURRENTPLAYER", GameInformation.CurrentPlayer);
                break;
            case "CURRENTPLAYERPHASE":
                GameInformation.CurrentPlayerPhase = (string)obj;
                PlayerPrefs.SetString("CURRENTPLAYERPHASE", GameInformation.CurrentPlayerPhase);
                break;
            default:
                Debug.Log("Error - Unrecognized tag <" + saveTag + ">.");
                break;
        }
    }

    public static void ToBinaryDataFile()
    {
        BinaryFormatter binary = new BinaryFormatter();
        FileStream fStream = File.Create(Application.persistentDataPath + "/saveFile.bin");
        SGameInformation gsaver = new SGameInformation();
        if (LoadInformation.FromGameInformation("NUMBEROFPLAYERSPLAYING") != null)
        {
            gsaver.NumberPlayers = LoadInformation.FromGameInformation("NUMBEROFPLAYERSPLAYING").ToString();
            if (LoadInformation.FromGameInformation("CURRENTPLAYER") != null)
            {
                gsaver.CurrentPlayer = LoadInformation.FromGameInformation("CURRENTPLAYER").ToString();
                if (LoadInformation.FromGameInformation("CURRENTPLAYERPHASE") != null)
                {
                    gsaver.CurrentPlayerPhase = LoadInformation.FromGameInformation("CURRENTPLAYERPHASE").ToString();

                    Environment.SetEnvironmentVariable("MONO_REFLECTION_SERIALIZER", "yes");
                    binary.Serialize(fStream, gsaver);
                 }
              }
          }
        fStream.Close();
    }
}

public class LoadInformation
{
    public static object FromGameInformation(string saveTag)
    {
        switch (saveTag)
        {
            case "NUMBEROFPLAYERSPLAYING":
                return GameInformation.NumberPlayers;
            case "CURRENTPLAYER":
                return GameInformation.CurrentPlayer;
            case "CURRENTPLAYERPHASE":
                return GameInformation.CurrentPlayerPhase;
            default:
                Debug.Log("Error - Unrecognized tag <" + saveTag + "> in switch() statement #1.");
                break;
        }
        return null;
    }
    public static void FromBinaryDataFile()
    {
        if (File.Exists(Application.persistentDataPath + "/saveFile.bin"))
        {
            BinaryFormatter binary = new BinaryFormatter();
            FileStream fStream = File.Open(Application.persistentDataPath + "/saveFile.bin", FileMode.Open);
            var gloader = (SGameInformation)binary.Deserialize(fStream) as SGameInformation;
            fStream.Close();

            SaveInformation.ToGameInformation("NUMBEROFPLAYERSPLAYING", gloader.NumberPlayers);
            SaveInformation.ToGameInformation("CURRENTPLAYER", gloader.CurrentPlayer);
            SaveInformation.ToGameInformation("CURRENTPLAYERPHASE", gloader.CurrentPlayerPhase);
            SaveInformation.ToPreferences();
        }
    }

P.S. Can’t seem to reply to your comments… so did answer again. Won’t submit otherwise.