Saving multiple values in isolated storage - c#

I am working on a Windows Phone 8 application. In my application, I have to store the scores of each attempt.
Eg:
1st attempt: orange 10 ,apple 20 ,mango 30.
2nd attempt: orange 5 ,apple 20 ,mango 25.
3rd attempt: orange 15 ,apple 25 ,mango 5.
and so on...
I have a score sheet where I need to show the values of each attempt.
This is how I am trying to save the values:
To write values
try
{
using (var store = IsolatedStorageFile.GetUserStoreForApplication())
{
using (StreamWriter sw = new StreamWriter(store.OpenFile(myObject.Title + "_State.xml", FileMode.Create, FileAccess.Write)))
{
XmlSerializer serializer = new XmlSerializer(typeof(MyObject));
serializer.Serialize(sw, myObject);
serializer = null;
}
}
}
catch (Exception)
{
throw;
}
To read
MyObject myObject = null;
try
{
using (IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForApplication())
{
// Read application settings.
if (isoStore.FileExists((myObject.Title + "_State.xml"))
{
using (var store = IsolatedStorageFile.GetUserStoreForApplication())
{
using (StreamReader SR = new StreamReader(store.OpenFile((myObject.Title + "_State.xml", FileMode.Open, FileAccess.Read)))
{
XmlSerializer serializer = new XmlSerializer(typeof(MyObject));
myObject = (MyObject)serializer.Deserialize(SR);
serializer = null;
}
}
}
else
{
// If setting does not exists return default setting.
myObject = new MyObject();
}
}
}
catch (Exception)
{
throw;
}
return myObject;
But in the above code, every time the values are replaced instead of added to previous values.
How do I add the attempts and their values to the same file?

Try to change FileMode when writing to the file to FileMode.Append instead of FileMode.Create :
store.OpenFile(myObject.Title + "_State.xml", FileMode.Append, FileAccess.Write)
About FileMode.Append from MSDN link above :
"Opens the file if it exists and seeks to the end of the file, or creates a new file. This requires FileIOPermissionAccess.Append permission. FileMode.Append can be used only in conjunction with FileAccess.Write. Trying to seek to a position before the end of the file throws an IOException exception, and any attempt to read fails and throws a NotSupportedException exception."

Related

How to read from local storage in xamarin android?

var sdcardpath = Android.OS.Environment.ExternalStorageDirectory.Path;
var filepath = System.IO.Path.Combine(sdcardpath, "first.html");
System.IO.StreamWriter writer = new StreamWriter(filepath, true);
if (!System.IO.File.Exists(filepath))
{
writer.Write(htmltext);
}
else
{
var txt = System.IO.File.ReadAllText(filepath);
}
In This Way I want to read an html from my local storage But while readalltext am getting exception
System.IO.IOException: Sharing violation on path /storage/emulated/0/first.html
When you do this
System.IO.StreamWriter writer = new StreamWriter(filepath, true);
it opens/creates a file at filepath. So after this the file always exists (given the path is correct and permissions allow). Then you try to read it but you have it open for writing so this will not be allowed.
If you're trying to see if the file exists and if not, write to it, then move the StreamWriter creation inside the check
if (!System.IO.File.Exists(filepath))
{
using (var writer = new StreamWriter(filepath, true))
{
writer.Write(htmltext);
}
}
else
{
var txt = System.IO.File.ReadAllText(filepath);
}

c# how to end streamreader

I am doing a project Windows form for assignment in Uni, I want to search an already created text file to match a first name and last name then write some additional information if the name and last name exist. I have the code constructed and showing no errors, however when I run and attempt to add information I am being provided with an error which essentially says the next process (Streamreader writer can not access the file as it is already in use by another process) I assume this process is streamreader, I have tried to code it to stop reading to no avail. I am in my first 3 months learning coding and would appreciate some assistance if possible, I have put a snippet of my code below.
//check if there is a file with that name
if (File.Exists(sFile))
{
using (StreamReader sr = new StreamReader(sFile))
{
//while there is more data to read
while (sr.Peek() != -1)
{
//read first name and last name
sFirstName = sr.ReadLine();
sLastName = sr.ReadLine();
}
{
//does this name match?
if (sFirstName + sLastName == txtSearchName.Text)
sr.Close();
}
//Process write to file
using (StreamWriter sw = new StreamWriter(sFile, true))
{
sw.WriteLine("First Name:" + sFirstName);
sw.WriteLine("Last Name:" + sLastName);
sw.WriteLine("Gender:" + sGender);
}
You are using your writer inside the reader, using the same file.
A using disposes the object inside it, after the closing curly braces.
using(StreamReader reader = new StreamReader("foo")){
//... some stuff
using(Streamwriter writer = new StreamWriter("foo")){
}
}
Do it like so :
using(StreamReader reader = new StreamReader("foo")){
//... some stuff
}
using(Streamwriter writer = new StreamWriter("foo")){
}
As per my comment regarding the using statement.
Rearrange to the below. I've tested locally and it seems to work.
using (StreamReader sr = new StreamReader(sfile))
{
//while there is more data to read
while (sr.Peek() != -1)
{
//read first name and last name
sFirstName = sr.ReadLine();
sLastName = sr.ReadLine();
//does this name match?
if (sFirstName + sLastName == txtSearchName.Text)
break;
}
}
using (StreamWriter sw = new StreamWriter(sfile, true))
{
sw.WriteLine("First Name:" + sFirstName);
sw.WriteLine("Last Name:" + sLastName);
sw.WriteLine("Gender:" + sGender);
}
I've replaced the sr.Close with a break statement to exit out. Closing the reader causes the subsequent peek to error as it's closed.
Also, I've noticed that you are not setting gender? unless its set elsewhere.
hope that helps
You can use FileStream. It gives you many options to work with file:
var fileStream = new FileStream("FileName", FileMode.Open,
FileAccess.Write, FileShare.ReadWrite);
var fileStream = new FileStream("fileName", FileMode.Open,
FileAccess.ReadWrite, FileShare.ReadWrite);
I think this is what you want/need. You can't append to a file the way you are trying to do it. Instead you'll want to read your input file, and write a temp file as you are reading through. And, whenever your line matches your requirements, then you can write the line with your modifications.
string inputFile = "C:\\temp\\StreamWriterSample.txt";
string tempFile = "C:\\temp\\StreamWriterSampleTemp.txt";
using (StreamWriter sw = new StreamWriter(tempFile))//get a writer ready
{
using (StreamReader sr = new StreamReader(inputFile))//get a reader ready
{
string currentLine = string.Empty;
while ((currentLine = sr.ReadLine()) != null)
{
if (currentLine.Contains("Clients"))
{
sw.WriteLine(currentLine + " modified");
}
else
{
sw.WriteLine(currentLine);
}
}
}
}
//now lets crush the old file with the new file
File.Copy(tempFile, inputFile, true);

Load XML document in read-only access mode

How do I load an XML document in read-only mode?
I have an XML file which is opened in another process and I want to load it in my C# application as read-only.
XmlDocument.Load("file.xml") obviously throws this error:
Process cannot access a file because it is being used by another
process
So I tried stream reader too:
FileStream fs = new FileStream("file.xml", FileMode.Open, FileAccess.Read);
xmldoc.Load(fs);
But it also throws the same error.
So how can I access my XML Document in read-only mode?
Update
I tried XPathDocument and FileStream("file.xml", FileMode.Open, FileAccess.Read,FileShare.Read) as well. But neither of them solved the problem.
This class Shows read xml file in read only mode.
public List<string[]> GetRunningOrderOnTable(string tableNo, int shopid)
{
try
{
XmlDocument xmlDoc = new XmlDocument();
string xmlFilePath = #"C:\inetpub\wwwroot\ShopAPI\XmlData\RunningTables.xml";
//string xmlFilePath = HttpContext.Current.Server.MapPath("~/XmlData/RunningTables.xml");
// Option 1
// FileStream xmlFile = new FileStream(xmlFilePath, FileMode.Open,
//FileAccess.Read, FileShare.Read);
// xmlDoc.Load(xmlFile);
// Option 2
using (Stream s = File.OpenRead(xmlFilePath))
{
xmlDoc.Load(s);
}
//xmlDoc.Load(xmlFilePath);
List<string[]> st = new List<string[]>();
XmlNodeList userNodes = xmlDoc.SelectNodes("//Tables/Table");
if (userNodes != null)
{
foreach (XmlNode userNode in userNodes)
{
string tblNo = userNode.Attributes["No"].Value;
string sid = userNode.Attributes["ShopID"].Value;
if (tblNo == tableNo && sid == shopid.ToString())
{
string[] str = new string[5];
str[0] = userNode.Attributes["No"].Value;
str[1] = userNode.InnerText; // OrderNumber
str[2] = userNode.Attributes["OrderID"].Value;
str[3] = userNode.Attributes["OrderedOn"].Value;
str[4] = userNode.Attributes["TotalAmount"].Value;
st.Add(str);
}
}
}
else return new List<string[]>();
return st;
}
catch (Exception ex)
{
CustomLogging.Log("RunningTables.xml GetRunningOrderOnTable Error " + ex.StackTrace, LoggingType.XMLRead);
return new List<string[]>();
}
}
Given you've said that FileShare.Read doesn't work, it would appear that the other process has the file open for writing.
You could try opening it with FileAccess.Read and FileShare.ReadWrite, in which case you'll need to handle any errors that may occur if the other process does actually write to the file.
If that doesn't work, it's likely that the other process has it opened with FileShare.None, in which case there's nothing you can do about it. To check this, try opening the file with, say, Notepad.
But is it still possible for FileShare.ReadWrite to throws error if it works in most cases?
You will only get an error if another process has already opened the file using FileShare.None. You've confirmed that this isn't the case when it's open in Microsoft Word, so you should be OK.

Operation not permitted on IsolatedStorageFileStream in WP8

I have seen numerous similar questions and I have really tried all the solutions but none seems to work for me.
This is what I have now:
private readonly object _lock = new object();
List<DataModel> dataList = new List<DataModel>();
lock (_lock)
{
using (IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
{
try
{
using (IsolatedStorageFileStream stream = myIsolatedStorage.OpenFile("Data.xml", FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite))
{
XmlSerializer serializer = new XmlSerializer(typeof(List<DataModel>));
dataList = (List<DataModel>)serializer.Deserialize(stream);
}
}
catch (IsolatedStorageException e) { e.ToString(); }
}
}
The error occurs on the line using (IsolatedStorageFileStream stream = myIsolatedStorage.OpenFile("Data.xml", FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite)).
I deduced from the other solutions that I read that this error mainly occurs when I want to write to the file while others are reading it or execute that code block several times concurrently, I end up locking the file."
With the presence of the lock, FileAccess.ReadWrite and FileShare.ReadWrite statements, I'm pretty sure something else is throwing that exception.
My question is what could be throwing the exception (IsolatedStorageException) and how do I take care of it?
There is no InnerException on this one.
Edit: Upon Kookiz suggestion, I'm including this code lines
First, I create my .xml file like this:
public static void createDataXML()
{
List<DataModel> dataList = new List<DataModel>();
using (IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
{
if (myIsolatedStorage.FileExists("Data.xml"))
{ return; }
using (IsolatedStorageFileStream stream = myIsolatedStorage.CreateFile("Data.xml"))
{
try
{
XmlSerializer serializer = new XmlSerializer(typeof(List<DataModel>));
serializer.Serialize(stream, dataList);
}
catch
{ }
}
}
}
Later, I populate with this code:
using (IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
{
using (IsolatedStorageFileStream stream = myIsolatedStorage.OpenFile("Data.xml", FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite))
{
XmlSerializer serializer = new XmlSerializer(typeof(List<DataModel>));
using (XmlWriter xmlWriter = XmlWriter.Create(stream, xmlWriterSettings))
{
serializer.Serialize(xmlWriter, dataList);
}
}
}
I know this is a less conventional way of doing this but it IS a way. I was attempting to do something else and this was the result. Just add in the known type you need and this will work
[DataContractAttribute]
[KnownType (typeof(List<String>))]
public class SerializableObject
{
[DataMember]
public List<String> serFile { get; set; }
}
public static Object GetFile(String FileName)
{
try
{
if (!IsolatedStorageFile.GetUserStoreForApplication().FileExists(FileName))
{
throw new System.ArgumentException("File Doesn't Exist In Isoloated Storage");
}
}
catch { return null; }
Object ret = new Object();
try
{
IsolatedStorageFile file = IsolatedStorageFile.GetUserStoreForApplication();
IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication();
IsolatedStorageFileStream fileStream = myIsolatedStorage.OpenFile(#"\" + FileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
SerializableObject serList = new SerializableObject();
DataContractSerializer dsc = new DataContractSerializer(serList.GetType());
ret = ((SerializableObject)dsc.ReadObject(fileStream)).serFile;
}
catch (Exception error) { throw new System.ArgumentException(error.Message); }
return ret;
}
The implied task here is that you need to serialize it within a SerializableObject instance. Let me know if you need that code also
Edit
As promised, the savefile function
public static void SaveFile(String FileName, List<String> File)
{
try
{
if (FileName.Length < 1)
{
throw new System.ArgumentException("File Name Must Not Be Empty");
}
if (IsolatedStorageFile.GetUserStoreForApplication().AvailableFreeSpace <= 0)
{
throw new System.ArgumentException("Isolated Storage Out of Memory - Please free up space.");
}
if (IsolatedStorageFile.GetUserStoreForApplication().FileExists(FileName))
{
throw new System.ArgumentException("File Already Exists - Please choose a unique name.");
}
if (File == null)
{
throw new System.ArgumentException("Cannot Save Null Files");
}
}
catch (Exception e)
{
return;
}
try
{
SerializableObject so = new SerializableObject() { serFile = File };
DataContractSerializer dsc = new DataContractSerializer(so.GetType());
IsolatedStorageFile file = IsolatedStorageFile.GetUserStoreForApplication();
StreamWriter writer;
writer = new StreamWriter(new IsolatedStorageFileStream(FileName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite, file));
dsc.WriteObject(writer.BaseStream, so);
}
catch (Exception error) { throw new System.ArgumentException(error.Message); }
}
Enjoy serializing!
My dear, though this exception of Operation Not Permitted On IsolatedStorage is mainly due to ReadWrite by another thread, in your case it is because of ONE SIMPLE REASON
FileMode.Open throws exception when the filename DOES NOT EXIST
Try with FileMode.OpenOrCreate and it will work like a charm
List<DataModel> dataList = new List<DataModel>();
using (IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
{
using (IsolatedStorageFileStream stream = myIsolatedStorage.OpenFile("Data.xml", FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite))
{
XmlSerializer serializer = new XmlSerializer(typeof(List<DataModel>));
dataList = (List<DataModel>)serializer.Deserialize(stream);
}
}

Datacontractserializer doesn't overwrite all data

I've noticed that if I persist an object back into file using a Datacontractserializer, if the length of the new xml is shorter than the xml originally present in the file the remnants of the original xml outwith the length of the new xml will remain in the file and will break the xml.
Does anyone have a good solution to fix this?
Here's the code I am using to persist the object:
/// <summary>
/// Flushes the current instance of the given type to the datastore.
/// </summary>
private void Flush()
{
try
{
string directory = Path.GetDirectoryName(this.fileName);
if (!Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}
FileStream stream = null;
try
{
stream = new FileStream(this.fileName, FileMode.OpenOrCreate);
for (int i = 0; i < 3; i++)
{
try
{
using (XmlDictionaryWriter writer = XmlDictionaryWriter.CreateTextWriter(stream, new System.Text.UTF8Encoding(false)))
{
stream = null;
// The serializer is initialized upstream.
this.serializer.WriteObject(writer, this.objectValue);
}
break;
}
catch (IOException)
{
Thread.Sleep(200);
}
}
}
finally
{
if (stream != null)
{
stream.Dispose();
}
}
}
catch
{
// TODO: Localize this
throw;
//throw new IOException(String.Format(CultureInfo.CurrentCulture, "Unable to save persistable object to file {0}", this.fileName));
}
}
It's because of how you are opening your stream with:
stream = new FileStream(this.fileName, FileMode.OpenOrCreate);
Try using:
stream = new FileStream(this.fileName, FileMode.Create);
See FileMode documentation.
I believe this is due to using FileMode.OpenOrCreate. If the file already exits, I think the file is being opened and parts of the data are being overwritten from the start byte. If you change to using FileMode.Create it forces any existing files to be overwritten.

Categories

Resources