I am currently creating a windows phone 7 application. How do I transform all the values of an array to textfile so I can print out all the values stored in that particular array inside another page listbox, and then store inside an isolated storage.
Thanks! :(
I tried this method but it doesn't work.
For ViewList.xaml.cs
private void addListBtn_Click(object sender, RoutedEventArgs e)
{
//Obtain the virtual store for application
IsolatedStorageFile myStore = IsolatedStorageFile.GetUserStoreForApplication();
//Create a new folder and call it "ImageFolder"
myStore.CreateDirectory("ListFolder");
//Create a new file and assign a StreamWriter to the store and this new file (myFile.txt)
//Also take the text contents from the txtWrite control and write it to myFile.txt
StreamWriter writeFile = new StreamWriter(new IsolatedStorageFileStream("ListFolder\\myFile.txt", FileMode.OpenOrCreate, myStore));
writeFile.WriteLine(retrieveDrinksListBox);
writeFile.Close();
}
FavouriteList.xaml.cs
private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
//Obtain a virtual store for application
IsolatedStorageFile myStore = IsolatedStorageFile.GetUserStoreForApplication();
//This code will open and read the contents of retrieveDrinksListBox
//Add exception in case the user attempts to click “Read button first.
StreamReader readFile = null;
try
{
readFile = new StreamReader(new IsolatedStorageFileStream("ListFolder\\myFile.txt", FileMode.Open, myStore));
string fileText = readFile.ReadLine();
if (fileText != "")
{
listNumberListBox.Items.Add("List 1");
}
//The control txtRead will display the text entered in the file
listNumberListBox.Items.Add(fileText);
readFile.Close();
}
catch
{
MessageBox.Show("Need to create directory and the file first.");
}
You must write away the serialized items/data of the listbox, not the listbox itself.
When reading them again, you must deserialize them.The BinaryFormatter example on MSDN has code samples showing you how to write away an object to a (file)stream and how to recover the object again from that same stream.
If you want to display contents of your file (say, lines) in listbox, read entire file content at once and split the lines:
string fileText = readFile.ReadToEnd();
string[] lines = fileText.Split(Enviroment.NewLine.ToCharArray(),
StringSplitOptions.RemoveEmptyEntries);
listNumberListBox.Items.AddRange(lines);
Other way around is similar, fetch items from your listbox, by joining them with new line, and dump at once to file:
string fileContents = string.Join(Environment.NewLine,
retrieveDrinksListBox.Items.Cast<string>());
writeFile.WriteLine(fileContents);
Related
I have a DataGridView which displays a list of rail cars and has several buttons for manipulating the list (Add, Edit, Delete, Save). The contents of the DGV come from an XML file and are saved back to the same file when the Save button is clicked. All functions of this form work perfectly with the exception of the Delete button. When I delete a rail car from the list and click Save, it takes the "deleted" row and re-appends it to the XML file in a very weird way (picture below).
Here is the code for the form (I'm only including the Save & Delete buttons and XML handling for ease of reading):
public partial class SimulatedTrainEditor : Form
{
//fileName and XML variables for serialization/deserialization
const string fileName = "SimulatedTrain1.xml";
XmlSerializer xml = new XmlSerializer(typeof(BindingList<SimulatedTrain>));
//Create BindingList object to hold XML data
public BindingList<SimulatedTrain> NewSimulatedTrain = new BindingList<SimulatedTrain>();
public bool WereChangesMade;
public SimulatedTrainEditor()
{
InitializeComponent();
LoadXML();
this.dataGridViewSimulatedTrainEditor.DataSource = NewSimulatedTrain;
this.dataGridViewSimulatedTrainEditor.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
this.dataGridViewSimulatedTrainEditor.AllowUserToAddRows = false;
this.WereChangesMade = false;
this.buttonSaveXML.Enabled = false;
}
public void LoadXML()
{
try
{
using (var fs = new FileStream(fileName, FileMode.Open))
{
NewSimulatedTrain = (BindingList<SimulatedTrain>)xml.Deserialize(fs);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message, ex);
}
}
private void buttonRemoveRailCar_Click(object sender, EventArgs e)
{
var currentRow = this.dataGridViewSimulatedTrainEditor.CurrentRow;
if (currentRow != null)
{
this.NewSimulatedTrain.RemoveAt(currentRow.Index);
this.WereChangesMade = true;
this.buttonSaveXML.Enabled = true;
}
}
private void buttonSaveXML_Click(object sender, EventArgs e)
{
//are there any changes?
if (WereChangesMade)
{
//save the file if changes
using (var fs = new FileStream(fileName, FileMode.OpenOrCreate))
{
xml.Serialize(fs, this.NewSimulatedTrain);
}
//Disable the SaveXML button when it's clicked to look for new edits after each save
this.buttonSaveXML.Enabled = false;
}
}
}
And here are screenshots of before and after I delete a row (this is just the bottom portion of the XML):
Before:
After (the red bit should be the end of the XML file):
You can see it tries to add another closing ArrayOfSimulatedTrain tag to the end after it throws in the row data that should have been deleted. I am still getting use to working with XML files, but in the few instances I've done this type of work before, I've never run into this particular issue.
Using FileStream in FileMode.OpenOrCreate mode does not wipe the content of file before writing.
Editing the XML changes the length of the content that will be written in the file. If the new XML is shorter, you will have some leftovers at the end of the file. From the MSDN :
If you overwrite a longer string (such as “This is a test of the OpenWrite method”) with a shorter string (such as “Second run”), the file will contain a mix of the strings (“Second runtest of the OpenWrite method”).
You need to change the FileMode of the stream to FileMode.Create to overwrite the whole file :
//save the file if changes
using (var fs = new FileStream(fileName, FileMode.Create))
{
xml.Serialize(fs, this.NewSimulatedTrain);
}
I have this very large text file (around 35 000+ lines of information) and I would like to extract certain lines from it and place them in another text file.
The text file goes like this:
Feature info
Feature name: 123456
Version: 1
Tokens total: 35
Tokens remaining: 10
And I'd like to extract Feature name and tokens total. What I had in mind was a form with two buttons: 1 for browsing the file and the other to do the whole reading and writing to file part, of course in the same line by line format.
Anyone have any clues on how to do it? I have searched and I haven't really found specific things, also quite new to file read/write...
EDIT
Ok here is what I have so far and it works:
private void button1_Click(object sender, EventArgs e)
{
int counter = 0;
string line;
string s1 = "Feature name";
string s2 = "Tokens total";
// Read the file and display it line by line.
System.IO.StreamReader file = new System.IO.StreamReader("d:\\license.txt");
using (System.IO.StreamWriter file2 = new System.IO.StreamWriter(#"D:\test.txt"))
while ((line = file.ReadLine()) != null)
{
if (line.Contains(s1) || line.Contains(s2))
{
file2.WriteLine(line);
counter++;
}
}
file.Close();
And this is done by a single button. What I want though is to be able to search for the file I want and then use another button in order to do all writing process
Answer for the EDIT:
You can store the read data in property or private field in the form class. Use String or StringBuilder preferably. When the second button is clicked check if there is stored data and write it to the output file.
private StringBuilder data = new StringBuilder();
private void button2_Click(object sender, EventArgs e)
{
if(data.Length > 0)
{
using(System.IO.StreamWriter file2 = new System.IO.StreamWriter(#"D:\test.txt"))
{
file2.Write(data.ToString());
}
}
}
private void button1_Click(object sender, EventArgs e)
{
// Clear the previous store data
data.Clear();
// ...
System.IO.StreamReader file = new System.IO.StreamReader("d:\\license.txt");
while ((line = file.ReadLine()) != null)
{
if (line.Contains(s1) || line.Contains(s2))
{
sb.AppendLine(line);
counter++;
}
}
file.Close();
}
Please add using for System.IO and surround your StreamReader and StreamWriter with using block so your code will be more readable and you won't forget to release the used resources.
You can use StreamReader and StreamWriter for read/write file
To extract specific part of text, you may use Regex.Matches, it will return Match, then you can retrieve the defined group in Match.Groups
// Search name
Match mu = Regex.Match(line, #"Feature name: (\d+)");
// Get name
if (mu.Groups.Count == 1) Console.Writeline(mu.Groups[0].Value);
When the app runs for the first time I'm adding items to a text file like so:
StringBuilder sb = new StringBuilder(); // Use a StringBuilder to construct output.
var store = IsolatedStorageFile.GetUserStoreForApplication(); // Create a store
store.CreateDirectory("testLocations"); // Create a directory
IsolatedStorageFileStream rootFile = store.CreateFile("locations.txt"); // Create a file in the root.
rootFile.Close(); // Close File
string[] filesInTheRoot = store.GetFileNames(); // Store all files names in an array
Debug.WriteLine(filesInTheRoot[0]); // Show first file name retrieved (only one stored at the moment)
string filePath = "locations.txt";
if (store.FileExists(filePath)) {
Debug.WriteLine("Files Exists");
StreamWriter sw =
new StreamWriter(store.OpenFile(filePath,
FileMode.Open, FileAccess.Write));
Debug.WriteLine("Writing...");
sw.WriteLine("Chicago, IL;");
sw.WriteLine("Chicago, IL (Q);");
sw.WriteLine("Dulles, VA;");
sw.WriteLine("Dulles, VA (Q);");
sw.WriteLine("London, UK;");
sw.WriteLine("London, UK (Q);");
sw.WriteLine("San Jose, CA;");
sw.WriteLine("San Jose, CA (Q);");
sw.Close();
Debug.WriteLine("Writing complete");
}
I can then view this data in a ListPicker using the follow code when a button is pressed, again all works well:
private void locChoice(object sender, RoutedEventArgs e)
{
IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication();
string filePath = "locations.txt";
if (store.FileExists(filePath))
{
Debug.WriteLine("Files Exists");
try
{
string fileData;
using (IsolatedStorageFileStream isoStream =
new IsolatedStorageFileStream("locations.txt", FileMode.Open, store))
{
using (StreamReader reader = new StreamReader(isoStream))
{
fileData = reader.ReadToEnd();
}
}
testLocationPicker.ItemsSource = fileData.Split(';');
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
testLocationPicker.Open();
}
I now want to add to the text file programmatically, which I'm doing like so, once users have filled in some text blocks:
StringBuilder sb = new StringBuilder(); // Use a StringBuilder to construct output.
var store = IsolatedStorageFile.GetUserStoreForApplication(); // Create a store
string[] filesInTheRoot = store.GetFileNames(); // Store all files names in an array
Debug.WriteLine(filesInTheRoot[0]); // Show first file name retrieved (only one stored at the moment)
string filePath = "locations.txt";
if (store.FileExists(filePath))
{
Debug.WriteLine("Files Exists");
StreamWriter sw =
new StreamWriter(store.OpenFile(filePath,
FileMode.Open, FileAccess.Write));
Debug.WriteLine("Writing...");
sw.WriteLine(locationName + ";"); // Semi Colon required for location separation in text file
sw.Close();
Debug.WriteLine(locationName + "; added");
Debug.WriteLine("Writing complete");
}
However, when I now go back to the previous page and click the button to view the entries in a ListPicker it turns out strange. The latest entry appears at the top with a large gap to the second place in the list. Adding another entry on top of that seems to hide the last entry.
The screenshot below should have to entries above the first "Chicago" entry. There should be a second Chicago entry that appears to have disappeared also.
Is there any way to browse to the created text file on the phone and see exactly how the data is laid out? This could give a clue.
Upon further investigation it appears when I write another line it is overwriting the existing text, rather than adding a new line. Any idea how to stop this?
I found some more documentation related to appending a file, which confirms my suspicion that the data was being overwritten.
The method I used when adding data now looks like this:
// ----------------------------------------------------------------
// Write the friend name to the locations text file upon submission
// ----------------------------------------------------------------
StringBuilder sb = new StringBuilder(); // Use a StringBuilder to construct output.
var store = IsolatedStorageFile.GetUserStoreForApplication(); // Create a store
string[] filesInTheRoot = store.GetFileNames(); // Store all files names in an array
Debug.WriteLine(filesInTheRoot[0]); // Show first file name retrieved (only one stored at the moment)
byte[] data = Encoding.UTF8.GetBytes(locationName + ";");
string filePath = "locations.txt";
if (store.FileExists(filePath))
{
using (var stream = new IsolatedStorageFileStream(filePath, FileMode.Append, store))
{
Debug.WriteLine("Writing...");
stream.Write(data, 0, data.Length); // Semi Colon required for location separation in text file
stream.Close();
Debug.WriteLine(locationName + "; added");
Debug.WriteLine("Writing complete");
}
}
Another Stack Overflow post helped me with the solution that didn't appear during my first search:
Does IsolatedStorage File.Append mode has an error with the the '\n'?
I am making simple tool for manipulating images in a database. I want to show the output result in a txt file and because the outcome may be different each time, I want the file to be rewritten with the fresh data every time the data is executed.
Also I want (if possible) to use some default location where the txt file will be created even though I have an App.Config file and that's also an option.
The problem I am having is with this code:
string Resultfile =
System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) +
"\\PictureStatus.txt";
FileStream strm = new FileStream(Resultfile , FileMode.Create);
TextWriter tw = new StreamWriter(strm);
This populates the PictureStatus.txt only once and then I get the same text over and over again. I noticed that if I use some random destination the file is updated. Not sure if it's just random behavior or have something to do with using MyDocuments, but what I need is a way to be sure that I'll rewrite the file with the new data each time, and if possible, use some default destination that will work for other people.
You can try something like this
public partial Form2 : Form
{
public string path = Environment.CurrentDirectory + "/" + "Name.txt";
public Form2()
{
InitializeComponent();
if (!File.Exists(path))
{
File.Create(path);
}
}
private void button2_Click(object sender, EventArgs e)
{
using (StreamWriter sw = new StreamWriter(path, true))
{
sw.WriteLine("This text will be writen in the txt file", true);
sw.Close();
}
}
}
I have add to the button, when I pressed it will be written in the next line every time. If you remove "true" from code, it will be overwritten every time.
I am able to do read/write/append operation on text file storing in isolated storage in WP7 application.
My scenario is that I am storing space seperated values in text file inside isolated storage.
So if I have to find for some particular line having some starting key then how to overwrite
value for that key without affecting the other line before and after it.
Example:
Key Value SomeOtherValue
*status read good
status1 unread bad
status2 null cantsay*
So if I have to change the whole second line based on some condition with key as same
status1 read good
How can I achieve this?
There are a number of ways you could do this, and the method you choose should be best suited to the size and complexity of the data file.
One option to get you started is to use the static string.Replace() method. This is crude, but if your file is only small then there is nothing wrong with it.
class Program
{
static void Main(string[] args)
{
StringBuilder sb = new StringBuilder();
sb.AppendLine("*status read good");
sb.AppendLine("status1 unread bad");
sb.AppendLine("status2 null cantsay*");
string input = sb.ToString();
var startPos = input.IndexOf("status1");
var endPos = input.IndexOf(Environment.NewLine, startPos);
var modifiedInput = input.Replace(oneLine.Substring(startPos, endPos - startPos), "status1 read good");
Console.WriteLine(modifiedInput);
Console.ReadKey();
}
}
If you store this information in text files then there won't be a way around replacing whole files. The following code does exactly this and might even be what you are doing right now.
// replace a given line in a given text file with a given replacement line
private void ReplaceLine(string fileName, int lineNrToBeReplaced, string newLine)
{
using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication())
{
// the memory writer will hold the read and modified lines
using (StreamWriter memWriter = new StreamWriter(new MemoryStream()))
{
// this is for reading lines from the source file
using (StreamReader fileReader = new StreamReader(new IsolatedStorageFileStream(fileName, System.IO.FileMode.Open, isf)))
{
int lineCount = 0;
// iterate file and read lines
while (!fileReader.EndOfStream)
{
string line = fileReader.ReadLine();
// check if this is the line which should be replaced; check is done by line
// number but could also be based on content
if (lineCount++ != lineNrToBeReplaced)
{
// just copy line from file
memWriter.WriteLine(line);
}
else
{
// replace line from file
memWriter.WriteLine(newLine);
}
}
}
memWriter.Flush();
memWriter.BaseStream.Position = 0;
// re-create file and save all lines from memory to this file
using (IsolatedStorageFileStream fileStream = new IsolatedStorageFileStream(fileName, System.IO.FileMode.Create, isf))
{
memWriter.BaseStream.CopyTo(fileStream);
}
}
}
}
private void button1_Click(object sender, RoutedEventArgs e)
{
ReplaceLine("test.txt", 1, "status1 read good");
}
And I agree with slugster: using SQLCE database might be a solution with better performance.