Xml Serializing and Writer - c#

in one class I create with a button click a XML document:
private void buttonCreate_Click(object sender, RoutedEventArgs e)
{
DialogResult result = folderElg.ShowDialog();
if (result == System.Windows.Forms.DialogResult.OK)
{
textBoxPath.Text = folderElg.SelectedPath;
userConfigurePath = folderElg.SelectedPath;
}
XmlDocument toolConfig = new XmlDocument();
XmlNode myRoot;
myRoot = toolConfig.CreateElement("Tool");
toolConfig.AppendChild(myRoot);
toolConfig.Save(#userConfigurePath + "\\config.xml");}
There I haven't problems. The folder is created and the xml file also.
So in an other class I want to serialize objects into the xml file 'config.xml' (The variable userConfigurePath is static in the classe mentionned above):
public partial class MainWindow : Window
{
private string inputNewTool = "";
private OpenFileDialog dlg = new OpenFileDialog();
public MainWindow()
{
InitializeComponent();
}
private void buttonAdd_Click(object sender, RoutedEventArgs e)
{
InputDialog input = new InputDialog();
input.ShowDialog();
inputNewTool = input.enteredTxt;
if (inputNewTool != null)
{
System.Windows.Forms.MessageBox.Show("Chose the Tool's directory");
dlg.DefaultExt = ".txt";
dlg.Filter = "Text documents (.txt)|*.txt";
if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
Tool tool = new Tool();
tool.Name = inputNewTool;
tool.Path = dlg.FileName;
XmlSerializer serializer = new XmlSerializer(tool.GetType());
StreamWriter writer = new StreamWriter(#Start.userConfigurePath +
"\\config.xml");
serializer.Serialize(writer.BaseStream, tool);
}
}
The result is that the object isn't saved in the config.xml file. Why?
Edit the Tool's Class:
public class Tool
{
public string Name { get; set; }
public string Path { get; set; }
public Tool() { }
}
Second Edit:
I see that i can't delete manuel these folder (after the application is closed) with the xml file when it is created. Why?
Third Edit:
I changed my Code so:
if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
Tool tool = new Tool();
tool.Name = inputNewTool;
tool.Path = dlg.FileName;
XmlSerializer serializer = new XmlSerializer(tool.GetType());
using (var writer = new StreamWriter(#Start.userConfigurePath +
"\\config.xml"))
{
serializer.Serialize(writer.BaseStream, tool);
writer.Close();
}
Now the first object is serialized. But if i create another tool in the same way the config.xml doesn't take it. Only the first tool is serialized:
<?xml version="1.0"?>
<Tool xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Name>dffss</Name>
<Path>D:\Users\xxxx\Documents\schulewochenbericht.txt</Path>
</Tool>

You need to close the StreamWriter object to flush the data into the file. Please try the following:
XmlSerializer serializer = new XmlSerializer(tool.GetType());
using (var writer = new StreamWriter(#Start.userConfigurePath + "\\config.xml"))
{
serializer.Serialize(writer.BaseStream, tool);
}

In addition to the answer from wdosanjos, you should also realize that you can't just write a sequence of Tool objects. If you want to write more than one Tool, then you need to write an array or list of Tool.

Related

How do I save information from an GUI into a XML-file?

I've created a program where users can input a few information and then can save everything into an xml file, or open it.
Before I setup that save and open thing on the bigger scale, I created a small test-run to find a solution. There are three textboxes where you can input your own information, two checkboxes and comboboxes where users can choose from a few options. I've created a open and save menu-strip-button but can't think of a way how to save all those information into a xml.file.
using System;
using System.IO;
using System.Windows.Forms;
namespace TestApp
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void openToolStripMenuItem_Click(object sender, EventArgs e)
{
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void openToolStripMenuItem_Click_1(object sender, EventArgs e)
{
var fileContent = string.Empty;
var filePath = string.Empty;
using (OpenFileDialog openFileDialog = new OpenFileDialog())
{
openFileDialog.InitialDirectory = "c:\\";
openFileDialog.Filter = "XML-File | *.xml|All files (*.*)|*.*";
openFileDialog.FilterIndex = 2;
openFileDialog.RestoreDirectory = true;
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
//Get the path of specified file
filePath = openFileDialog.FileName;
//Read the contents of the file into a stream
var fileStream = openFileDialog.OpenFile();
using (StreamReader reader = new StreamReader(fileStream))
{
fileContent = reader.ReadToEnd();
}
}
}
//MessageBox.Show(fileContent, "File Content at path: " + filePath, MessageBoxButtons.OK);
}
private void saveToolStripMenuItem_Click(object sender, EventArgs e)
{
Stream myStream;
SaveFileDialog saveFileDialog1 = new SaveFileDialog();
saveFileDialog1.Filter = "XML-File | *.xml|All files (*.*)|*.*";
saveFileDialog1.FilterIndex = 2;
saveFileDialog1.RestoreDirectory = true;
if (saveFileDialog1.ShowDialog() == DialogResult.OK)
{
if ((myStream = saveFileDialog1.OpenFile()) != null)
{
// Code to write the stream goes here.
myStream.Close();
}
}
}
/*private void validateUserEntry()
{
// Checks the value of the text.
if (textBox1.Text.Length == 0 && textBox2.Text.Length == 0 && textBox3.Text.Length == 0)
{
// Initializes the variables to pass to the MessageBox.Show method.
string message = " AAAAAAAAAAAAA";
string caption = "Error Detected in Input";
MessageBoxButtons buttons = MessageBoxButtons.YesNo;
DialogResult result;
// Displays the MessageBox.
result = MessageBox.Show(message, caption, buttons);
if (result == System.Windows.Forms.DialogResult.Yes)
{
// Closes the parent form.
this.Close();
}
}
}*/
}
}
I use the library I wrote by using the System.Xml.Serialization library in XML operations.
You can download the source codes or use them with the nuget package manager.
ioCode.Serialization
C# types serialization library.
Serializes and deserializes objects into and from XML documents.
PM> Install-Package ioCode.Serialization -Version 1.0.0
Classes
ioCode.Serialization library has two serialization classes
XmlSerializer<T> Xml serialization object to serialize custom types
BinSerializer<T> Bin serialization object for XML-based serialization of custom types. The serialized output file is encrypted.
XmlSerializer<T>
Write to file
Product product = new Product();
product.Name = "Product1";
bool isSuccess = XmlSerializer<Product>.WriteFile(#"C:\users\[user]\documents\product.xml", product);
MessageBox.Show(isSuccess ? "Success" : "Fail");
Read from file
Product product = XmlSerializer<Product>.ReadFile(#"C:\users\[user]\documents\product.xml");
MessageBox.Show((product != null) ? "Success" : "Fail");
BinSerializer<T>
Write to file
Product product = new Product();
product.Name = "Product1";
bool isSuccess = BinSerializer<Product>.WriteFile(#"C:\users\[user]\documents\product.bin", "password123", product);
MessageBox.Show(isSuccess ? "Success" : "Fail");
Read from file
Product product = BinSerializer<Product>.ReadFile(#"C:\users\[user]\documents\product.bin", "password123");
MessageBox.Show((product != null) ? "Success" : "Fail");

C# serialization UIElementCollection

I have some code:
public static UIElementCollection DeSerializeXAML(string filename)
{
// Load XAML from file. Use 'using' so objects are disposed of properly.
using (System.IO.FileStream fs = System.IO.File.Open(filename, System.IO.FileMode.Open, System.IO.FileAccess.Read))
{
return System.Windows.Markup.XamlReader.Load(fs) as UIElementCollection; //EXCEPTION
}
}
// Serializes any UIElement object to XAML using a given filename.
public static void SerializeToXAML(UIElementCollection elements, string filename)
{
// Use XamlWriter object to serialize element
string strXAML = System.Windows.Markup.XamlWriter.Save(elements);
// Write XAML to file. Use 'using' so objects are disposed of properly.
using (System.IO.FileStream fs = System.IO.File.Create(filename))
{
using (System.IO.StreamWriter streamwriter = new System.IO.StreamWriter(fs))
{
streamwriter.Write(strXAML);
}
}
}
private void btnSave_Click(object sender, RoutedEventArgs e)
{
SaveFileDialog dlg = new SaveFileDialog();
dlg.FileName = "UIElement File"; // Default file name
dlg.DefaultExt = ".xaml"; // Default file extension
dlg.Filter = "Xaml File (.xaml)|*.xaml"; // Filter files by extension
// Show save file dialog box
Nullable<bool> result = dlg.ShowDialog();
// Process save file dialog box results
if (result == true)
{
// Save document
string filename = dlg.FileName;
SerializeToXAML(myCanvas.Children, filename);
}
}
private void btnLoad_Click(object sender, RoutedEventArgs e)
{
Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
dlg.DefaultExt = ".xaml"; // Default file extension
dlg.Filter = "Xaml File (.xaml)|*.xaml"; // Filter files by extension
// Show open file dialog box
Nullable<bool> result = dlg.ShowDialog();
// Process open file dialog box results
if (result == true)
{
string filename = dlg.FileName;
UIElementCollection elements = DeSerializeXAML(filename) as UIElementCollection;
// Add all child elements (lines, rectangles etc) to canvas
myCanvas.Children.Clear();
foreach (UIElement el in elements)
{
myCanvas.Children.Add(el);
}
}
}
That works fine with serialization but when you deserialize, an exception is thrown.
Text of exception(translated with google):"You did not find a suitable constructor for the type" System.Windows.Controls.UIElementCollection.
"You can use the Arguments or FactoryMethod directives to generate this type.": Line number "1" and position in line "22".
A UIElementCollection instance is tied to a specific Visual, and as such, it is unsuitable for serialization (as #kostya-k points out). The deserialization logic doesn't know how to create a new UIElementCollection because it doesn't know which Visual to associate it with. And creating a new collection is pointless anyway, as you are simply transferring the values to myCanvas.Children.
The good news is that you can use a XamlObjectWriter to populate myCanvas.Children directly instead of instantiatating a new collection:
public static void DeSerializeXAML(UIElementCollection elements, string filename)
{
var context = System.Windows.Markup.XamlReader.GetWpfSchemaContext();
var settings = new System.Xaml.XamlObjectWriterSettings
{
RootObjectInstance = elements
};
using (var reader = new System.Xaml.XamlXmlReader(filename))
using (var writer = new System.Xaml.XamlObjectWriter(context, settings))
{
System.Xaml.XamlServices.Transform(reader, writer);
}
}
private void btnLoad_Click(object sender, RoutedEventArgs e)
{
Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
dlg.DefaultExt = ".xaml"; // Default file extension
dlg.Filter = "Xaml File (.xaml)|*.xaml"; // Filter files by extension
// Show open file dialog box
Nullable<bool> result = dlg.ShowDialog();
// Process open file dialog box results
if (result == true)
{
string filename = dlg.FileName;
myCanvas.Children.Clear();
DeSerializeXAML(myCanvas.Children, filename);
}
}
UIElementCollection is not intended for serialization. It meant to be used when building a WPF visual tree.

The process cannot access the file 'E:\test.txt' because it is being used by another process

I'm trying to remove out-of-sequence white spaces from a text file to one-space sequence in a winForm i.e.,
From
sagchjvcsj kbschjsdchs sudbjsdbl
sdvbchjbvsdjc kbsadcsadk kskbjdsdcksajdbc
To
sagchjvcsj kbschjsdchs sudbjsdbl
sdvbchjbvsdjc kbsadcsadk kskbjdsdcksajdbc
My implementation is:
private void buttonBrowse_Click(object sender, EventArgs e)
{
Stream myStream;
OpenFileDialog openFileDialogImage = new OpenFileDialog();
openFileDialogImage.Filter = "Text files | .txt";
openFileDialogImage.Multiselect = false;
if (openFileDialogImage.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
if ((myStream = openFileDialogImage.OpenFile()) != null)
{
textBoxFileName.Text = openFileDialogImage.FileName;
}
}
}
private void buttonGo_Click(object sender, EventArgs e)
{
string path = textBoxFileName.Text;
string s = string.Empty;
using (StreamReader reader = new StreamReader(path, true))
{
s = reader.ReadToEnd();
}
string[] parts = s.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
SaveFileDialog saveFileDialog = new SaveFileDialog();
saveFileDialog.ShowDialog();
string pathSave = saveFileDialog.FileName;
File.CreateText(pathSave);
using (StreamWriter sw = new StreamWriter(pathSave))
{
sw.Write(parts);
}
}
}
}
Error that I am getting on line using (StreamWriter sw = new StreamWriter(pathSave)) is:
The process cannot access the file 'E:\test.txt' because it is being used by another process.
I downloaded ProcessWorker to see which process is currently locking Test.txt but I don't see any process using it. Any ideas on how to solve it?
In addition to the other suggestions, your problem is that File.CreateText() will lock so you need to release the lock. I have wrapped the call to File.CreateText() in a using statement to release the lock.
There was an issue with the output of the StreamWriter so I made some changes to get the expected output as per your question.
private void buttonGo_Click(object sender, EventArgs e)
{
string path = textBoxFileName.Text;
string s = string.Empty;
string[] parts;
using (StreamReader reader = new StreamReader(path, true))
{
parts = reader.ReadToEnd().Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
}
SaveFileDialog saveFileDialog = new SaveFileDialog();
saveFileDialog.ShowDialog();
string pathSave = saveFileDialog.FileName;
using (File.CreateText(pathSave))
{ }
using (StreamWriter sw = new StreamWriter(pathSave))
{
string result = string.Empty;
foreach (string s in parts)
{
result += s + " ";
}
sw.Write(result);
}
}

Visual Studio 2010 C# - Loading saved file from file explorer into application

I have a Windows Form program that you enter data in to, that data can be saved to a XML format file, I am giving it my own extention of .WSDA, I'd like to be able to without having the program loaded, click this file and have it run the same routine i use to save it.
Here are the events for saving and loading the files via button...
private void button11_Click(object sender, EventArgs e)
{
// Opens Dialog Box
SaveFileDialog saveFileDialog1 = new SaveFileDialog();
saveFileDialog1.Filter = "Workspace Data File |*.wsda";
saveFileDialog1.Title = "Save current Workspace data.";
saveFileDialog1.ShowDialog();
if (saveFileDialog1.FileName != "")
{
// Create an instance of the FormData class and populate it with form data..
FormData FormSave = new FormData();
FormSave.form_type = textForm.Text;
FormSave.policy_num = textPolicynum.Text;
FormSave.effective_date = textEffdate.Text;
FormSave.sai_number = textSAI.Text;
FormSave.office_code = textOffice.Text;
FormSave.change_date = textChgdate.Text;
FormSave.name_insured = textNamedIns.Text;
FormSave.error_code = textErrorCode.Text;
FormSave.producer_code = textProducer.Text;
FormSave.nticid = textNtic.Text;
FormSave.notes = textNotes.Text;
// Create and XmlSerializer to serialize the data.
XmlSerializer xs = new XmlSerializer(typeof(FormData));
// XmlTextWriter writes file.
XmlTextWriter xtw = new XmlTextWriter(new StreamWriter(saveFileDialog1.FileName));
xs.Serialize(xtw, FormSave);
// Stop writing to file.
xtw.Flush();
xtw.Close();
}
}
private void button12_Click(object sender, EventArgs e)
{
// Opens Dialog Box
OpenFileDialog openFileDialog1 = new OpenFileDialog();
openFileDialog1.Filter = "Workspace Data File |*.wsda";
openFileDialog1.Title = "Save current Workspace data.";
openFileDialog1.ShowDialog();
if (openFileDialog1.FileName != "")
{
//XmlTextReader Reads file.
XmlSerializer xs = new XmlSerializer(typeof(FormData));
XmlTextReader xtw = new XmlTextReader(openFileDialog1.FileName);
FormData FormLoad = new FormData();
//Converts it to form data again.
FormLoad = xs.Deserialize(xtw) as FormData;
//Updates the fields with the data file.
textForm.Text = FormLoad.form_type;
textPolicynum.Text = FormLoad.policy_num;
textEffdate.Text = FormLoad.effective_date;
textSAI.Text = FormLoad.sai_number;
textOffice.Text = FormLoad.office_code;
textProducer.Text = FormLoad.producer_code;
textChgdate.Text = FormLoad.change_date;
textNamedIns.Text = FormLoad.name_insured;
textErrorCode.Text = FormLoad.error_code;
textNtic.Text = FormLoad.nticid;
textNotes.Text = FormLoad.notes;
// Stop Reading File.
xtw.Close();
}
}
I found a work for what I needed to accomplish.
Program.cs I made with the following.
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
if (args.Length == 1) //make sure an argument is passed
{
FileInfo file = new FileInfo(args[0]);
if (file.Exists) //make sure it's actually a file
{
File.Copy(file.FullName, "./workspace.tmp"); //copys the associated file to the program folder and renames it.
// This is importants since the name of the file can be anything *.wsda
}
}
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}
Then in the actual form I run a IF statement for a temp file to load which the program.cs handles, as you see its then copied to workspace.tmp
This parses the file and sets the form textbox values to that of the loaded file.
if (System.IO.File.Exists("./workspace.tmp"))
{
//XmlTextReader Reads file.
XmlSerializer xs = new XmlSerializer(typeof(FormData));
XmlTextReader xtw = new XmlTextReader("./workspace.tmp");
FormData FormLoad = new FormData();
//Converts it to form data again.
FormLoad = xs.Deserialize(xtw) as FormData;
//Updates the fields with the data file.
textForm.Text = FormLoad.form_type;
textPolicynum.Text = FormLoad.policy_num;
textEffdate.Text = FormLoad.effective_date;
textSAI.Text = FormLoad.sai_number;
textOffice.Text = FormLoad.office_code;
textProducer.Text = FormLoad.producer_code;
textChgdate.Text = FormLoad.change_date;
textNamedIns.Text = FormLoad.name_insured;
textErrorCode.Text = FormLoad.error_code;
textNtic.Text = FormLoad.nticid;
textNotes.Text = FormLoad.notes;
// Stop Reading File.
xtw.Close();
File.Delete("./workspace.tmp"); // since its done loading it, deletes the file.
}

There is an error in XML document (0, 0) during deserialization

i have the following code to for xml serialization.
public class FormSaving
{
private string major;
public string Majorversion
{
get;
set;
}
}
private void SaveButton_Click(object sender, RoutedEventArgs e)
{
string savepath;
SaveFileDialog DialogSave = new SaveFileDialog();
// Default file extension
DialogSave.DefaultExt = "txt";
// Available file extensions
DialogSave.Filter = "XML file (*.xml)|*.xml|All files (*.*)|*.*";
// Adds a extension if the user does not
DialogSave.AddExtension = true;
// Restores the selected directory, next time
DialogSave.RestoreDirectory = true;
// Dialog title
DialogSave.Title = "Where do you want to save the file?";
// Startup directory
DialogSave.InitialDirectory = #"C:/";
DialogSave.ShowDialog();
savepath = DialogSave.FileName;
DialogSave.Dispose();
DialogSave = null;
FormSaving abc = new FormSaving();
abc.Majorversion = MajorversionresultLabel.Content.ToString();
using (Stream savestream = new FileStream(savepath, FileMode.Create))
{
XmlSerializer serializer = new XmlSerializer(typeof(FormSaving));
serializer.Serialize(savestream, abc);
}
}
private void LoadButton_Click(object sender, RoutedEventArgs e)
{
Stream checkStream = null;
Microsoft.Win32.OpenFileDialog DialogLoad = new Microsoft.Win32.OpenFileDialog();
DialogLoad.Multiselect = false;
DialogLoad.Filter = "XML file (*.xml)|*.xml|All files (*.*)|*.*";
if ((bool)DialogLoad.ShowDialog())
{
try
{
if ((checkStream = DialogLoad.OpenFile()) != null)
{
loadpath = DialogLoad.FileName;
checkStream.Close();
}
}
catch (Exception ex)
{
System.Windows.MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message);
}
}
else
{
System.Windows.MessageBox.Show("Problem occured, try again later");
}
FormSaving abc;
using (Stream loadstream = new FileStream(loadpath, FileMode.Create))
{
XmlSerializer serializer = new XmlSerializer(typeof(FormSaving));
abc = (FormSaving)serializer.Deserialize(loadstream);
}
MajorversionresultLabel.Content = abc.Majorversion;
}
When i press the SaveButton, my label.content is saved into an xml file. However when i press the load button to load this xml file, i get the error "There is an error in XML document (0, 0)". I went to open my xml file after pressing the load button, it becomes blank and everything got erased. Can anyone help me fix this load button error?
ok solved,
using (Stream loadstream = new FileStream(loadpath, FileMode.Open))
{
XmlSerializer serializer = new XmlSerializer(typeof(FormSaving));
abc = (FormSaving)serializer.Deserialize(loadstream);
}
should have been FileMode.Open instead of FileMode.Create

Categories