Easiest way to write/read class - c#

I'm new to C# and Windows Phone developing, I need to do app for school project.
I have simple class, and I want to save it to have access later, on next start of application.
What is the best (and easiest) method to do that? Using file, database or some other application memory?
Here is my class:
public class Place
{
private string name;
private string description;
private int distance;
private bool enabled;
private GeoCoordinate coordinates;
}
I need to store multiple instances of class.

There is no "best" way to do it; it depends on how you're going to use it.
A simple way is to use serialization, to XML, JSON, binary or whatever you want. I personally like JSON, as it's very lightweight and easy to read for a human. You can use the JSON.NET library to serialize objects to JSON.
For instance, if you want to serialize a collection of Place to a file, you can do something like that:
static async Task SavePlacesAsync(ICollection<Place> places)
{
var serializer = new JsonSerializer();
var folder = ApplicationData.Current.LocalFolder;
var file = await folder.CreateFileAsync("places.json", CreationCollisionOption.ReplaceExisting);
using (var stream = await file.OpenStreamForWriteAsync())
using (var writer = new StreamWriter(stream))
{
serializer.Serialize(writer, places);
}
}
And to read it back from the file:
static async Task<ICollection<Place>> LoadPlacesAsync()
{
try
{
var serializer = new JsonSerializer();
var folder = ApplicationData.Current.LocalFolder;
var file = await folder.GetFileAsync("places.json");
using (var stream = await file.OpenStreamForReadAsync())
using (var reader = new StreamReader(stream))
using (var jReader = new JsonTextReader(reader))
{
return serializer.Deserialize<ICollection<Place>>(jReader, places);
}
}
catch(FileNotFoundException)
{
return new List<Place>();
}
}

I think the easiest way to make persistent your object is to store them in a file. However this is not the best way due to the time spent in IO operations, low security, etc.
Here you have a nice example:
How to quickly save/load class instance to file

Related

Deserialize object one by one from file .Net

I'm trying to deserialize a list of heavy objects from a json file. I do not want to deserialize it the classic way, like directly to a list, because it will expose me to an OutOfMemory exception. So I'm looking for a way to handle object one by one to store them one by one in the database and be memory safe.
I already handle the serialization and it's working well, but I'm facing some difficulties for deserialization.
Any idea ?
Thanks in advance
// Serialization
using (var FileStream = new FileStream(DirPath + "/TPV.Json", FileMode.Create))
{
using (var sw = new StreamWriter(FileStream))
{
using (var jw = new JsonTextWriter(sw))
{
jw.WriteStartArray();
using (var _Database = new InspectionBatimentsDataContext(TheBrain.DBClient.ConnectionString))
{
foreach (var TPVId in TPVIds)
{
var pic = (from p in _Database.TPV
where Operators.ConditionalCompareObjectEqual(p.Release, TPVId.Release, false) & Operators.ConditionalCompareObjectEqual(p.InterventionId, TPVId.InterventionId, false)
select p).FirstOrDefault;
var ser = new JsonSerializer();
ser.Serialize(jw, pic);
jw.Flush();
}
}
jw.WriteEndArray();
}
}
}
I finnaly found a way to do it by using custom separator beetween each object during serialization. Then for deserialization, I simply read the json file as string until I find my custom separator and I deserialise readed string, all in a loop. It's not the perfect answer because I'm breaking json format in my files, but it's not a constraint in my case.

Xamarin Forms download a json file with httpclient : ReadAsStringAsync or DownloadFileAsync?

I use a json file for populate listview in a Xamarin Forms Android/Ios app and like to download the json file on start.
Is it better to use ReadAsStringAsync or DownloadFileAsync?
DownloadFileAsync is not for binary only? nut maybe fastestthen read string and write it :)
Thanks
Typically you want to download JSON content and deserialize directly to a model. For example:
private sealed class YourModel
{
public int SomeProperty { get; set; }
public string SomeOtherProperty { get; set; }
}
using (var req = await _httpClient.GetAsync("https://www.example.com/api/endpoint"))
{
req.EnsureSuccessStatusCode();
using (var s = await req.Content.ReadAsStreamAsync())
using (var sr = new StreamReader(s))
using (var jtr = new JsonTextReader(sr))
{
var obj = new JsonSerializer().Deserialize<YourModel>();
}
}
There are extensions you can use that make this simpler, for example, if you imported the System.Net.Http.HttpClientExtensions nuget package then you could do this:
using (var req = await _httpClient.GetAsync("https://www.example.com/api/endpoint"))
{
EnsureSuccessStatusCode();
var obj = await req.Content.ReadAsAsync<YourModel>();
}
If you don't want to use models, then typically JSON content would be downloaded as string.
If you are going to directly save the data to disk as a file, use DownloadFileAsync() - it will be a simpler and faster solution than ReadAsStringAsync() because DownloadFileAsync() will use streams to write content in files, instead of first reading network data as a string and writing it to file stream with StreamWriter.
String is never good for performance. Even if you want to parse that JSON content downloaded from the network in code directly instead of saving on disk, you can read response with ReadAsStreamAsync() and you that stream to deserialize JSON object with JsonSerializer.

How to use System.IO Serializers in UWP with Windows.Storage

I want to be able to have a list of class objects (List<Class>) and be able to easily write and read to a text file.
In my older Console Applications and Windows Forms applications I used to use:
List<Class> _myList = ...
WriteToFile<List<Class>>("C:\\...\\Test.txt", Class _myList)
public static void WriteToFile<T>(string filePath, T objectToWrite, bool append = false) where T : new()
{
TextWriter writer = null;
try
{
var serializer = new XmlSerializer(typeof(T));
writer = new StreamWriter(filePath, append);
serializer.Serialize(writer, objectToWrite);
}
finally
{
if (writer != null)
writer.Close();
}
}
However this does not work in a UWP application and I have to use StorageFolder and StorageFile which works fine for writing simple text to a file like this:
StorageFolder folder = Windows.Storage.ApplicationData.Current.LocalFolder;
StorageFile file= await storageFolder.GetFileAsync("Test.txt");
await FileIO.WriteTextAsync(sampleFile, "Example Write Text");
But I want to be able to use the more advanced functionality of XmlSerializer along with StreamWriter to write lists of classes to a file within my UWP application.
How can I do this?
You can use the Stream-based versions the methods you use, for example StreamWriter has a constructor which takes a System.IO.Stream instance.
To get a System.IO.Stream from a StorageFile, you can use the OpenStreamForWriteAsync and OpenStreamForReadAsync extension methods, which are in the System.IO namespace on UWP:
//add to the top of the file
using System.IO;
//in your code
var stream = await myStorageFile.OpenStreamForWriteAsync();
//do something, e.g.
var streamWriter = new StreamWriter(stream);

How to save a file in LocalStorage?

I have an ObservableCollection <T>. I want to insert the various elements in it and then save the newly created file in LocalStorage. How can I do that?
SQLiteAsyncConnection conn = new SQLiteAsyncConnection(Path.Combine(ApplicationData.Current.LocalFolder.Path, "Database.db"), true);
await conn.CreateTableAsync<Musei>();
var Dbase = Path.Combine(ApplicationData.Current.LocalFolder.Path, "Database.db");
var con = new SQLiteAsyncConnection(Dbase, true);
var query = await con.Table<Musei>().ToListAsync();
ObservableCollection<Musei> favMusei = new ObservableCollection<Musei>();
if (query.Count > 0)
{
favMusei.Clear();
foreach (Musei museifav in query)
{
favMusei.Add(museifav);
}
}
I'm using a json file to store in the memory. JSON is a light weight message exchange format and is widely used. You have to do some slight modifications in the code if you want some different file format.
Your collection would be serialized to the memory at the time of saving and has to be deserialized when reading it back from memory.
Add your own generic implementation of the collection. To create your situation i'm using a simple ObservableCollection<int>. And don't forget to initialize the collection to some meaningful values, here i'm using the default constructor initialization.
using System.Collections.ObjectModel;
using System.Runtime.Serialization.Json;
using Windows.Storage;
//Add your own generic implementation of the collection
//and make changes accordingly
private ObservableCollection<int> temp;
private string file = "temp.json";
private async void saveToFile()
{
//add your items to the collection
temp = new ObservableCollection<int>();
var jsonSerializer = new DataContractJsonSerializer(typeof(ObservableCollection<int>));
using (var stream = await ApplicationData.Current.LocalFolder.OpenStreamForWriteAsync(file, CreationCollisionOption.ReplaceExisting))
{
jsonSerializer.WriteObject(stream, temp);
}
}
private async Task getFormFile()
{
var jsonSerializer = new DataContractJsonSerializer(typeof(ObservableCollection<int>));
try
{
using (var stream = await ApplicationData.Current.LocalFolder.OpenStreamForReadAsync(file))
{
temp = (ObservableCollection<int>)jsonSerializer.ReadObject(stream);
}
}
catch
{
//if some error is caught while reading data from the file then initializing
//the collection to default constructor instance is a good choice
//again it's your choice and may differ in your scenario
temp = new ObservableCollection<int>();
}
}
To add some functionality to the code you can also have an ensureDataLoaded() function which would ensure that the data has been read from the JSON file.
public async Task ensureDataLoaded()
{
if (temp.Count == 0)
await getFormFile();
return;
}
Before using the global variable temp (having the ObservableCollection) call the ensureDataLoaded function. It would avoid some unnecessary NullPointerExceptions.

How to save a Dictionary variable in roaming - C#

After studying the manual of Visual C#, I'm starting to program a simple app for Windows 8. I'm using Visual Studio 2013 Express and .NET Framework 4.5.1. In the code I've written up to now, in the code-behind of a page I create a list of people:
private Dictionary<string, People> listPeople = new Dictionary<string, People>();
After this, I wish this list would fill a ComboBox control of another page. The solution I thought is to save the Dictionary<string, People> variable in roaming, and then use it where I need. In this way also would solve the problem of maintaining the list of people saved even when the app is terminated.
How can I do?
did you already try it like that?
var applicationData = Windows.Storage.ApplicationData.Current;
applicationData.RoamingSettings.Values["PeopleList"] = listPeople;
var applicationData = Windows.Storage.ApplicationData.Current;
var listPeople = (Dictionary<string, People>)applicationData.RoamingSettings.Values["PeopleList"];
The overwhelming advice is to serialize your setting as a string then set the value in Values (or save the values in the complex type individually).
But, I think that really ignores the fact that Values is a series of key-value pairs... If you want to support complex types, I think creating your own file in the roaming folder is a better idea. I've written a small helper class to accomplish this via JSON serialization:
public class ApplicationStorageHelper
{
private static readonly JsonSerializer jsonSerializer = JsonSerializer.Create();
public static async Task<bool> SaveData<T>(T data)
{
var file =
await ApplicationData.Current.RoamingFolder.CreateFileAsync("settings.dat", CreationCollisionOption.ReplaceExisting);
using (var stream = await file.OpenAsync(FileAccessMode.ReadWrite))
{
using (var outputStream = stream.GetOutputStreamAt(0))
{
using (var writer = new StreamWriter(outputStream.AsStreamForWrite()))
{
var jsonWriter = new JsonTextWriter(writer);
jsonSerializer.Serialize(jsonWriter, data);
return true;
}
}
}
}
public static async Task<T> LoadData<T>()
{
try
{
var file =
await ApplicationData.Current.RoamingFolder.GetFileAsync("settings.dat");
using (var inputStream = await file.OpenSequentialReadAsync())
{
using (var reader = new StreamReader(inputStream.AsStreamForRead()))
{
var jsonReader = new JsonTextReader(reader);
return jsonSerializer.Deserialize<T>(jsonReader);
}
}
}
catch (FileNotFoundException)
{
return default(T);
}
}
}
You'll have to reference JSON.Net from Nuget or some other way.

Categories

Resources