How can i store any variable in a file and load that in runtime specifically using a string in maui c#?

188 views Asked by At

I want to save variables in a file which will have specific keys and I want to load it using that keys.Suggest me two functions (that can take and use any variable and class as parameter) to that as cross platform approach in maui C#.I tried the code below and got the error.

tried this code:

public static void StoreData<T>(string key, T value)
{
    
    try
    {
        // Load existing data or create a new dictionary
        Dictionary<string, T> data;

        string filePath = Path.Combine(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), AppInfo.Current.Name), "data.json");

        if (!Directory.Exists(Path.Combine(
                Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
                AppInfo.Current.Name)))

        {
            Directory.CreateDirectory(Path.Combine(
                Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
                AppInfo.Current.Name));
        }

        if (!File.Exists(filePath))
        {
            File.Create(filePath);
        }

        using (StreamReader reader = new StreamReader(filePath))
        {
            data = new Dictionary<string, T>();
            string json = reader.ReadToEnd();
            data = JsonSerializer.Deserialize<Dictionary<string, T>>(json);
        }

        data[key] = value;

        // Add or update the value associated with the key

        // Serialize and save the updated data to the file
        using (StreamWriter writer = new StreamWriter(filePath))
        {
            string json = JsonSerializer.Serialize(data);
            writer.Write(json);
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Failed to save data: {ex.Message}");
    }
}

// Load data based on a key as an identifier
public static T LoadData<T>(string key, T defaultValue = default)
{
    try
    {
        // Load existing data or return the default value
        Dictionary<string, T> data;
        string filePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "data.json");

        if (File.Exists(filePath))
        {
            using (StreamReader reader = new StreamReader(filePath))
            {
                string json = reader.ReadToEnd();
                data = JsonSerializer.Deserialize<Dictionary<string, T>>(json);

                if (data != null)
                {
                    if (data.ContainsKey(key))
                    {
                        return data[key];
                    }
                }
            }
        }

        return defaultValue;
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Failed to load data: {ex.Message}");
        return defaultValue;
    }
}

Error is

System.Text.Json.JsonException
  HResult=0x80131500
  Message=The input does not contain any JSON tokens. Expected the input to start with a valid JSON token, when isFinalBlock is true. Path: $ | LineNumber: 0 | BytePositionInLine: 0.
  Source=System.Text.Json
  StackTrace:
   at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& state, JsonReaderException ex)
   at System.Text.Json.Serialization.JsonConverter`1.ReadCore(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state)
   at System.Text.Json.JsonSerializer.ReadFromSpan[TValue](ReadOnlySpan`1 utf8Json, JsonTypeInfo jsonTypeInfo, Nullable`1 actualByteCount)
   at System.Text.Json.JsonSerializer.ReadFromSpan[TValue](ReadOnlySpan`1 json, JsonTypeInfo jsonTypeInfo)
   at System.Text.Json.JsonSerializer.Deserialize[TValue](String json, JsonSerializerOptions options)
   at book_companion_3.DataStorage.StoreData[T](String key, T value) in K:\Windows For Programming\Projects\Visual Studio\Apps\Maui\book companion 3\DataStorage.cs:line 78

  This exception was originally thrown at this call stack:
    [External Code]

Inner Exception 1:
JsonReaderException: The input does not contain any JSON tokens. Expected the input to start with a valid JSON token, when isFinalBlock is true. LineNumber: 0 | BytePositionInLine: 0.
1

There are 1 answers

10
Liyun Zhang - MSFT On

I have tested your code and met some problems:

1. About the following part code:

        using (StreamReader reader = new StreamReader(filePath))
        {
            data = new Dictionary<string, T>();
            string json = reader.ReadToEnd();
            data = JsonSerializer.Deserialize<Dictionary<string, T>>(json);
        }

This will throw an data cast exception when your data types are different between this time and the last time.

2. The file path of the storing and loading are different.

In the storing, it is:

Path.Combine(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), AppInfo.Current.Name), "data.json");

But in the loading it is:

Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "data.json");

It missed the AppInfo.Current.Name. So I deleted the code in the first problem and changed the path in the loading method.

    public partial class MainPage : ContentPage
    {
        public static void StoreData<T>(string key, T value)
        {
            try
            {
                // Load existing data or create a new dictionary
                Dictionary<string, T> data;

                string filePath = Path.Combine(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), AppInfo.Current.Name), "data.json");

                if (!Directory.Exists(Path.Combine(
                        Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
                        AppInfo.Current.Name)))

                {
                    Directory.CreateDirectory(Path.Combine(
                        Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
                        AppInfo.Current.Name));
                }

                if (!File.Exists(filePath))
                {
                    File.Create(filePath);
                }
                data = new Dictionary<string, T>();
                data[key] = value;

                // Add or update the value associated with the key

                // Serialize and save the updated data to the file
                using (StreamWriter writer = new StreamWriter(filePath))
                {
                    string json = JsonSerializer.Serialize(data);
                    writer.Write(json);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Failed to save data: {ex.Message}");
            }
        }

// Load data based on a key as an identifier
        public static T LoadData<T>(string key, T defaultValue = default)
        {
            try
            {
                // Load existing data or return the default value
                Dictionary<string, T> data;
                string filePath = Path.Combine(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), AppInfo.Current.Name), "data.json");
                if (File.Exists(filePath))
                {
                    using (StreamReader reader = new StreamReader(filePath))
                    {
                        string json = reader.ReadToEnd();
                data = JsonSerializer.Deserialize<Dictionary<string, T>>(json);

                        if (data != null)
                        {
                            if (data.ContainsKey(key))
                            {
                                return data[key];
                            }
                        }
                    }
                }

                return defaultValue;
            }
            catch (Exception ex)
            {
            Console.WriteLine($"Failed to load data: {ex.Message}");
            return defaultValue;
            }
        }

        public MainPage()
        {
            InitializeComponent();
        }

        private void Button_Clicked(object sender, EventArgs e)
        {
           StoreData<List<string>>("hello",new List<string>() { "ASD","AAA"});
        }

        private void Button_Clicked_1(object sender, EventArgs e)
        {
           var value = LoadData<List<string>>("hello",new List<string>());
        }
    }

After this, I can store the data and load it.

Update:

Change writer.Write to writer.WriteAsync will resolve the error op met.