I'm working on an UWP application where a user can input data which is placed in a listview. All fine and dandy, but how can I save the user data to a separate file and load it the next time a user boots up the app?
I've tried to find a solution, but I had great difficulty to understand these code snippets and on how to apply these (since I'm fairly new to C# and App development). Would somebody like to explain how I can achieve the saving/loading of the data and explain what the code does?
Thanks in advance! :)
You can create a file like this:
StorageFile ageFile = await local.CreateFileAsync("Age.txt", CreationCollisionOption.FailIfExists);
I can read and write to a file like this:
StorageFolder local = Windows.Storage.ApplicationData.Current.LocalFolder;
var ageFile = await local.OpenStreamForReadAsync(#"Age.txt");
// Read the data.
using (StreamReader streamReader = new StreamReader(ageFile))
{
//Use like a normal streamReader
}
if you are trying to write, use OpenStreamForWriteAsync;
If I understood well, you have some kind of object structure that serves as a model for your ListView. When the application is started, you want to read a file where the data is present. When closing the application (or some other event) write the file with the changes done. Right?
1) When your application is loaded / closed (or upon modifications or some event of your choice), use the Windows.Storage API to read / write the text into the file.
2) If the data you want to write is just a liste of strings, you can save this as is in the file. If it is more complicated, I would recommend serializing it in JSON format. Use JSON.NET to serialize (object -> string) and deserialize (object <- string) the content of your file and object structure.
Product product = new Product();
product.Name = "Apple";
...
string json = JsonConvert.SerializeObject(product);
Related
I have a .txt file that i process into a List in my program.
I would like to somehow save that List and include it in the program itself so that it loads every time the program starts, so I don't have to process it every time from a .txt file.
Its more complicated than just "int x = 3;" cause it has like 10k lines and I don't wanna copy paste all that in the beginning.
I've looked all over but haven't found anything similar, any ideas guys?
Also if thee's a solution, can it work with any type (arrays, Dictionaries)?
As requested, the code is:
var text = System.IO.File.ReadAllText(#"C:\Users\jazz7\Desktop\links_zg.txt");
EDIT
Joe suggested the solution:
Included the file within the project, set its "build action" to embedded resource in Properties and used this code:
private string linkovi = "";
...
var assembly = Assembly.GetExecutingAssembly();
var resourceName = "WindowsFormsApplication4.links_zg.txt";
using (Stream stream = assembly.GetManifestResourceStream(resourceName))
using (StreamReader reader = new StreamReader(stream))
{
linkovi = reader.ReadToEnd();
}
string linkovi now contains the txt file and is now within the application. Thanks all!
You could store the file as a resource in your executable file.
This KB article describes how to do it.
Fundamentally, youve got to choose between storing your data in memory or storing it on the hard drive. The former will cut your loading time, but might use an unacceptable amount of memory, whilst the latter is slower, as youve identified. Either way, your data has to be stored somewhere.
Do you need to load all of the data at once? If the loading time is the issue, you could process the file line by line. While this would be slower overall, you would still have access to some usable data sooner.
I found this great tutorial for loading XML using XLINQ (LINQ to XML).
http://www.codearsenal.net/2012/07/c-sharp-load-xml-using-xlinq.html
It helped me a lot and I got the job done with it.
The only change I made was where he had this line:
from e in XDocument.Load(#"..\..\Employees.xml").Root.Elements("employee")
I write it like this:
from el in XDocument.Load("XML_Files/Employees.xml").Root.Elements("employee")
I had to change the path like this to access a local xml file found right inside my Visual Studio project.
But now I need to save the data back to the file in my project solution. Again, my xml file is located inside my C# project. It's not on the desktop or anything, it is a file added to the project solution.
I can't seem to find any good resources for how to do this task. Does anyone know a good tutorial, or code, a reference to start?
I am inserting a list of objects into the xml files. The objects have basic data type properties, except for one of the object properties, which is a List of doubles.
Can anyone advise a good tutorial or link? Or even a generic code sample?
I'd like to keep this function as basic as possible.
Please help.
------------------ UPDATE ------------------
I actually got this kind of working now. The below code does what I need EXCEPT that it won't write the data to my local file in the Visual Studio project. It will gladly write the data to a test file I created on my desktop, however.
Does anyone know why this is??
//create the serialiser to create the xml
XmlSerializer serialiser = new XmlSerializer(typeof(List<Student>));
// Create the TextWriter for the serialiser to use
TextWriter Filestream = new StreamWriter(#"C:\\Users\\MyName\\Desktop\\output.xml");
//write to the file
serialiser.Serialize(Filestream, employees);
// Close the file
Filestream.Close();
-------- UPDATE ---------
Okay, figured it out.
This code works:
public void WriteXML()
{
//create the serialiser to create the xml
XmlSerializer serialiser = new XmlSerializer(typeof(List<Student>));
// Create the TextWriter for the serialiser to use
TextWriter Filestream = new StreamWriter(#"XML_Files\Employees.xml");
//write to the file
serialiser.Serialize(Filestream, employees);
// Close the file
Filestream.Close();
}
The data is inserted to the xml file, but it does not show in Visual Studio. But when I checked here:
C:\Users\Me\Desktop\MyProject\MyProject\bin\Debug\XML_Files
The file is overwritten.
Also, when I reload the data from the application again, the new entries come up.
The problem is in line:
TextWriter Filestream = new StreamWriter(#"C:\\Users\\MyName\\Desktop\\output.xml");
Change it to one of following:
TextWriter Filestream = new StreamWriter("C:\\Users\\MyName\\Desktop\\output.xml");
TextWriter Filestream = new StreamWriter(#"C:\Users\MyName\Desktop\output.xml");
Simply remove the "#", OR use single slashes:
This problem is somewhat similar to this.
In my case, I have a text file. And since there is no content importer that works for text file, I have to write my own functions using stream readers. What I am trying to accomplish is to read from the text file, and set a few values accordingly into the options screen. I have added all necessary references, but using "../options.txt" as filepath does not work. Quite possibly the filepath is resolved to something else than Content folder. How do I then proceed with it?
Also, I am getting errors saying "attempt to access method (System.IO....ctor) failed". Is it that I am missing to add some other reference?
Does this have to work on the xBox 360? If so it's not possible to just use the filesystem like you can in Windows, you'll need to use a storage device. To be honest I would just use this method anyway so if you decide to take your game on to WP7 or 360 it'll just work.
There is a nice demo game that loads and saves data on this Microsoft page as well as a description of what it's doing
This is taken from the demo, it shows how to open a storage container and serialize some config data to it, the load operation is just as simple.
// Create the data to save.
SaveGameData data = new SaveGameData();
data.PlayerName = "Hiro";
data.AvatarPosition = new Vector2(360, 360);
data.Level = 11;
data.Score = 4200;
// Open a storage container.
IAsyncResult result =
device.BeginOpenContainer("StorageDemo", null, null);
// Wait for the WaitHandle to become signaled.
result.AsyncWaitHandle.WaitOne();
StorageContainer container = device.EndOpenContainer(result);
// Close the wait handle.
result.AsyncWaitHandle.Close();
string filename = "savegame.sav";
// Check to see whether the save exists.
if (container.FileExists(filename))
// Delete it so that we can create one fresh.
container.DeleteFile(filename);
// Create the file.
Stream stream = container.CreateFile(filename);
// Convert the object to XML data and put it in the stream.
XmlSerializer serializer = new XmlSerializer(typeof(SaveGameData));
serializer.Serialize(stream, data);
// Close the file.
stream.Close();
// Dispose the container, to commit changes.
container.Dispose();
i am working on a pc 192.168.2.200
i have made a simple C# Windows application on 192.168.2.200
I want to Create a Text File on D: of a Network PC whose IP is 192.168.2.201 and UserName is abc and Password is 123 by C# code in Windows Application
How i Will Create file on Network PC
any one can Help me
System.IO.File.Create(#"D:\myfile.txt");
OR
System.IO.File.WriteAllText(#"D:\myfile.txt","Hello this is my File");
Windows application or not, you'd use the same technique. If you don't care what the format is, but want to use it as an input file that you read/write from, then you might want to look into XmlSerializer, along with a custom class that you write (with username/password/IP properties).
Here is a simple tutorial on XML serialization:
http://www.switchonthecode.com/tutorials/csharp-tutorial-xml-serialization
If you want a custom format, and only want to write to it (such as a log file), then you can do this:
var file = System.IO.File.Create("file.txt");
var writer = new System.IO.StreamWriter(file);
writer.WriteLine("fjkldsaf");
Or use the overload for StreamWriter that takes a filename:
var writer = new System.IO.StreamWriter("otherfile.txt");
writer.WriteLine("some text");
Keep in mind that writing a password in clear text onto your hard drive is not very secure (same with clear-text over the network, though I know you're not asking about that).
Make sure you either call Dispose or Close on your file streams when you're done with them. You can stick them in a using block to do this automatically (even if an exception is accidentally thrown in your file writing code).
using(var writer = new System.IO.StreamWriter("otherfile.txt"))
{
writer.WriteLine("some text");
}
I have a text file with a list of 300,000 words and the frequency with wich they occur. Each line is in the format Word:FequencyOfOccurence.
I want this information to be accessible from within the C# code. I can't hard code the list since it is too long, and I'm not sure how to go about accessing it from a file on the server. Ideally I'd ideally like the information to be downloaded only if it's used (To save on bandwidth) but this is not a high priority as the file is not too big and internet speeds are always increasing.
It doesn't need to be useable for binding.
The information does not need to be editable once the project has been built.
Here is another alternative. Zip the file up and stick it in the clientBin folder next to the apllication XAP. Then at the point in the app where the content is needed do something like this:-
public void GetWordFrequencyResource(Action<string> callback)
{
WebClient client = new WebClient();
client.OpenReadAsync += (s, args) =>
{
try
{
var zipRes = new StreamResourceInfo(args.Result, null)
var txtRes = Application.GetResourceStream(zipRes, new Uri("WordFrequency.txt", UriKind.Relative));
string result = new StreamReader(txtRes.Stream).ReadToEnd();
callback(result);
}
catch
{
callback(null); //Fetch failed.
}
}
client.OpenReadAsync(new Uri("WordFrequency.zip", UriKind.Relative"));
}
Usage:-
var wordFrequency = new Dictionary<string, int>();
GetWordFrequencyResource(s =>
{
// Code here to burst string into dictionary.
});
// Note code here is asynchronous with the building of the dictionary don't attempt to
// use the dictionary here.
The above code allows you to store the file in an efficient zip format but not in the XAP itself. Hence you can download it on demand. It makes use of the fact that a XAP is a zip file so Application.GetResourceStream which is designed to pull resources from XAP files can be used on a zip file.
BTW, I'm not actually suggesting you use a dictionary, I'm just using a dictionary as simple example. In reality I would imagine the file is in sorted order. If that is the case you could use a KeyValuePair<string, int> for each entry but create a custom collection type that holds them in an array or List and then use some Binary search methods to index into it.
Based on your comments, you could download the word list file if you are required to have a very thin server layer. The XAP file containing your Silverlight application is nothing more than a ZIP file with all the referenced files for your Silverlight client layer. Try adding the word list as content that gets compiled into the XAP and see how big the file gets. Text usually compresses really well. In general, though, you'll want to be friendly with your users in how much memory your application consumes. Loading a huge text file into memory, in addition to everything else you need in your app, may untimately make your app a resource hog.
A better practice, in general, would be to call a web service. The service could would perform whatever look up logic you need. Here's a blog post from a quick search that should get you started: (This was written for SL2, but should apply the same for SL3.)
Calling web services with Silverlight 2
Even better would be to store your list in a SQL Server. It will be much easier and quicker to query.
You could create a WCF service on the server side that will send the data to the Silverlight application. Once you retrieve the information you could cache it in-memory inside the client. Here's an example of calling a WCF service method from Silverlight.
Another possibility is to embed the text file into the Silverlight assembly that is deployed to the client:
using (var stream = Assembly.GetExecutingAssembly()
.GetManifestResourceStream("namespace.data.txt"))
using (var reader = new StreamReader(stream))
{
string data = reader.ReadToEnd();
// Do something with the data
}