I was reading a book on serialization. I am confused about implementing class portion or simply put i don't really understand classes(maybe).
Basically i have my application designed in this way following the steps of my book. I just dont understand the class of FileSaving and maybe where to implement it. I would like to start using serialization to save elements of a form and reloading it via xml using a "Save" and "Load" button. I have a textbox and users keys in strings into the Majorversiontextbox and this textbox.text is then stored as MajorversionLabel. Please clarify my doubts and help me out with serialization. Thanks! I will clarify any doubts about my question.
EDIT
Question 1, Why do i need to have this FileSaving class when I am only getting values from the content from the label and saving it into a xml file. Question 2, is my FileSaving class declared correctly? Question 3, why do i need Get and Set over here?
public partial class Window1 : Window
{
...
...
public class FileSaving
{
private string major;
public string Majorversion
{
get
{
return major;
}
set
{
major = value;
}
}
}
private void MajorversionupdateButton_Click(object sender, RoutedEventArgs e)
{
MajorversionresultLabel.Content = MajorversionTextBox.Text;
MajorversionupdateButton.Visibility = Visibility.Hidden;
MajorversionTextBox.Visibility = Visibility.Hidden;
MajorversionmodifyButton.Visibility = Visibility.Visible;
}
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;
Filesaving abc = new FileSaving();
abc.Majorversion = MajorversionLabel.Content;
FileStream savestream = new FileStream(path, FileMode.Create);
XmlSerializer serializer = new XmlSerializer(typeof(FileSaving));
serializer.Serialize(savestream, abc);
}
private void LoadButton_Click(object sender, RoutedEventArgs e)
{
string loadpath;
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;
}
}
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");
}
FileSaving abc = new FileSaving();
FileStream loadstream = new FileStream(loadpath, FileMode.Open);
XmlSerializer serializer = new XmlSerializer(typeof(FileSaving));
abc=(FileSaving)serializer.Deserialize(loadstream);
loadstream.Close();
MajorversionresultLabel.Content = abc.Majorversion;
}
}
because XmlSerializer is an object serializer, and works from the type definition
sure, that'll work
strictly speaking you don't, but the current version looks fine; XmlSerializer works for public properties or fields; you could simplify to an automatically-implemented property though: public string MajorVersion {get;set;}
But if you only want to save a single string value - is xml overfkill? File.WriteAllText / File.ReadAllText may be simpler.
Related
My issue is that I keep seeing a recurring theme with trying to allow my Notepad clone to save a file. Whenever I try to save a file, regardless of the location on the hard disk, the UnauthorizedAccess Exception continues to be thrown. Below is my sample code for what I've done, and I have tried researching this since last night to no avail. Any help would be greatly appreciated.
//located at base class level
private const string fileFilter = "Text Files|*.txt|All Files|*.*";
private string currentPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
private void MenuFileSaveAs_Click(object sender, RoutedEventArgs e)
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.DefaultExt = "*.txt";
sfd.Filter = fileFilter;
sfd.AddExtension = true;
sfd.InitialDirectory = currentPath;
sfd.RestoreDirectory = true;
sfd.OverwritePrompt = true;
sfd.ShowDialog();
try
{
System.IO.File.WriteAllText(currentPath,TxtBox.Text,Encoding.UTF8);
}
catch (ArgumentException)
{
// Do nothing
}
catch(UnauthorizedAccessException)
{
MessageBox.Show("Access Denied");
}
}
Change the following lines.
...
if (sfd.ShowDialog() != true)
return;
try
{
using (var stream = sfd.OpenFile())
using (var writer = new StreamWriter(stream, Encoding.UTF8))
{
writer.Write(TxtBox.Text);
}
}
...
I hope it helps you.
You need to get the correct path context and file object from the dialog box once the user has hit 'ok'. Namely verify the user actually hit ok and then use the OpenFile property to see what their file selection is:
if (sfd.ShowDialog.HasValue && sfd.ShowDialog)
{
if (sfd.OpenFile() != null)
{
// convert your text to byte and .write()
sfd.OpenFile.Close();
}
}
I've got this code at the start of the form that reads a file that already exists and sets value of 4 textBoxes accordingly to what it's written inside. How do I proceed if the file hasn't yet been created? Any help would be very appreciated.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
FileStream file = new FileStream("cenaEnergentov.txt", FileMode.Open, FileAccess.Read);
StreamReader sr = new StreamReader(file);
sr.ReadLine();
var textLines = File.ReadAllLines("cenaEnergentov.txt");
foreach (var line in textLines)
{
string[] dataArray = line.Split(';');
textBox1.Text = (dataArray[0]);
textBox2.Text = (dataArray[1]);
textBox3.Text = (dataArray[2]);
textBox4.Text = (dataArray[3]);
}
}
If the uper is a false I'd like to proceed with normal script down below that starts with:
public void trackBar1_Scroll(object sender, EventArgs e)
{
......
Use a simple if statement
// I edit this line according to your comment
if(File.Exists(String.Concat("cenaEnergentov".ToUpper(), ".txt"))
{
// do your job
}
else
{
// call appropriate method
trackBar1_Scroll(this,EventArgs.Empty); // for example
}
Try this before you open the file:
var filename = "filename.txt";
if (!File.Exists(filename))
{
File.Create(filename);
}
This won't account for the fact that you're assigning values without checking to see if they exist first. Implementing that is relatively trivial as well.
It also appears that the FileStream and StreamReader are redundant. Just use File.ReadAllLines instead.
The previous solutions will work OK... however they don't really answer the big question:
How do I know when to continue?
The best way would be to use a FileSystemWatcher:
var watcher = new FileSystemWatcher(path, ".txt");
watcher.Created += (sender, e) =>
{
if (e.ChangeType == WatcherChangeTypes.Created)
initForm();
};
Where initForm() is:
void initForm()
{
if(File.Exists(path))
{
// Update form
}
else
{
var watcher = new FileSystemWatcher(path, ".txt");
watcher.Created += (sender, e) =>
{
if (e.ChangeType == WatcherChangeTypes.Created)
initForm();
};
}
}
try this
if(File.Exists("yourFile.txt"))
{
//do what you do
}
else
{
// call appropriate method
}
I am having trouble calling the string "rlist" from:
public void main()
{
string rlist;
if (radioButton1.Checked)
textBox1.Enabled = false;
textBox1.ReadOnly = true;
rlist = "text";
}
to
public void button1_Click(object sender, EventArgs e)
{
OpenFileDialog openFile = new OpenFileDialog();
openFile.Filter = "WTF Files (*.wtf)|*.wtf";
openFile.Title = "Please Pick your realmlist file:";
if (openFile.ShowDialog() == DialogResult.Cancel)
return;
try
{
textBox5.Text = openFile.FileName;
string file = openFile.FileName;
TextWriter rlist_writer = new StreamWriter (openFile.FileName);
rlist_writer.WriteLine(rlist);
rlist_writer.Close();
}
catch (Exception)
{
MessageBox.Show("Error opening file", "File Error",
MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
}
I get the error on this line:
rlist_writer.WriteLine(rlist);
is it possible to call a string from one function and send it to the other with the same value it had in the function it was originally pulled from?
By the sounds of your question,
Your string is local to your main function.
So judging by your method names and knowledge of winforms(presumed again)
you need to make your string class level
string rlist;
public void main()
{
rlist = "yay"
public void button1_Click(object sender, EventArgs e)
{
someText = rlist;
As it currently stands you are not able to, as temporary (local) variables will be cleaned through garbage collection when you leave the method
Edit
You may wish to review this also
try
{
textBox5.Text = openFile.FileName;
using(TextWriter rlist_writer = new StreamWriter (openFile.FileName))
{
rlist_writer.WriteLine(rlist);
}
}
You can define that variable in your class scope, then if you call that variable in your button_click event, it will maintain the same value as in your main method.
I have this code that takes a file path that is obtained with the OpenFileDialog and attempts to save it to an xml file. For some reason the xml doc will not get written if one of the nodes contains a string from this open file dialog. An exception will not get thrown and the app will not crash, just the file will not get written.
If I use a string literal in place of the m_strSoundFile with the same contents, the xml document will get written correctly. So it has nothing to do with the '\' character being illegal, which is what I initially thought. Maybe it has something to do with the fact that the OpenFileDialog is Win32? Any help would be appreciated.
Thanks,
Alex
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
string m_strSoundFile;
public MainWindow()
{
InitializeComponent();
}
private void btnChooseFile_Click(object sender, RoutedEventArgs e)
{
Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
dlg.Filter = "Wav files (*.wav)|*.wav"; // Filter files by extension
dlg.InitialDirectory = #"C:\windows\media";
Nullable<bool> result = true;
bool pathExists = false;
do
{
result = dlg.ShowDialog();
if (result == true)
{
pathExists = dlg.CheckPathExists;
if (!pathExists)
MessageBox.Show("Path does not exist");
else
m_strSoundFile = dlg.FileName;
}
} while (result == true && !pathExists);
m_tbFilename.Text = m_strSoundFile;
}
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
XmlDocument xmlDoc = new XmlDocument();
XmlNode xmlRootNode = xmlDoc.CreateElement("Settings");
XmlNode node = xmlDoc.CreateElement("File");
XmlAttribute a = xmlDoc.CreateAttribute("Path");
a.Value = m_strSoundFile;
node.Attributes.Append(a);
xmlRootNode.AppendChild(node);
xmlDoc.AppendChild(xmlRootNode);
System.IO.FileStream fs;
try
{
fs = System.IO.File.Open("configfile.xml", System.IO.FileMode.Create, System.IO.FileAccess.Write);
xmlDoc.Save(XmlWriter.Create(fs, new XmlWriterSettings() { Indent = true, Encoding = Encoding.UTF8 }));
fs.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
Ok, I figured it out. After using an absolute path for the filestream it worked. It's still weird that it works conditionally when not using an absolute path.
Quite new to OO so please be kind.
I have created a method which when button1 is clicked, opens a file dialog and reads the contents into a stream reader sr;
public void button1_Click(object sender, EventArgs e)
{
if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
label1.Text = openFileDialog1.FileName;
StreamReader sr = new StreamReader(label1.Text);
String strNumVertices = sr.ReadLine();
label2.Text = strNumVertices;
}
}
The other code runs in the Form1_Paint method.
public void Form1_Paint(object sender, PaintEventArgs e)
perspectiveMatrix = new Gmatrix("perspective");
translationMatrix = new Gmatrix("translation");
scalingMatrix = new Gmatrix("scaling");
perspectiveMatrix.initAsPerspectiveMatrix(300);
scalingMatrix.initAsScalingMatrix(10, 10, 10);
translationMatrix.initAsTranslationMatrix(150, 50, 1200);
String strNumVertices = sr.ReadLine();
label1.Text = strNumVertices;
My question is, How do I reference stream reader sr from the button1_click method in the Form1_paint method?
Word of advice - don't try.
If you do so, you are in danger of having open files/streams all over the place.
I suggest you open a new steam reader in each method (or abstract it away into its own method).
Note:
You should be wrapping the opening of the stream in a using statement, to ensure proper disposal:
using(StreamReader sr = new StreamReader(label1.Text))
{
String strNumVertices = sr.ReadLine();
label2.Text = strNumVertices;
}
Actually, it should be not the best idea to read from the stream during each paint run. Perhaps you'd like to read the value once, store it in the member variable of your form, and access in the paint method?
Unless you expect the file to have changed between the button click and the paint method being called then you shouldn't be reading from the file again anyway.
Reading the file is very expensive in terms of performance compared to storing the result in a field and retreiving it during the paint method. Or visa versa depending what executes first.
Make it a field on the form class. This changes the scope from the method to the entire form. The warnings from the previous post are still valid.
StreamReader sr;
public void button1_Click(object sender, EventArgs e)
{
if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
label1.Text = openFileDialog1.FileName;
sr = new StreamReader(label1.Text);
String strNumVertices = sr.ReadLine();
label2.Text = strNumVertices;
}
}
public void Form1_Paint(object sender, PaintEventArgs e)
perspectiveMatrix = new Gmatrix("perspective");
translationMatrix = new Gmatrix("translation");
scalingMatrix = new Gmatrix("scaling");
perspectiveMatrix.initAsPerspectiveMatrix(300);
scalingMatrix.initAsScalingMatrix(10, 10, 10);
translationMatrix.initAsTranslationMatrix(150, 50, 1200);
if (sr != null) {
String strNumVertices = sr.ReadLine();
label1.Text = strNumVertices;
}
Why not just store the data you've read from the file and re-use it rather than reading the file again? I'm assuming these methods are in the same class (and the same instance of the object), but there are ways around that if that's not true.
private string StrNumVertices { get; set; }
public void button1_Click(object sender, EventArgs e)
{
if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
label1.Text = openFileDialog1.FileName;
StreamReader sr = new StreamReader(label1.Text);
this.StrNumVertices = sr.ReadLine();
label2.Text = this.StrNumVertices;
}
}
public void Form1_Paint(object sender, PaintEventArgs e)
perspectiveMatrix = new Gmatrix("perspective");
translationMatrix = new Gmatrix("translation");
scalingMatrix = new Gmatrix("scaling");
perspectiveMatrix.initAsPerspectiveMatrix(300);
scalingMatrix.initAsScalingMatrix(10, 10, 10);
translationMatrix.initAsTranslationMatrix(150, 50, 1200);
label1.Text = this.StrNumVertices;
...
}
If it's not the same instance of the object, then I'd consider using a Singleton configuration object (or cache) and storing the data there. It really depends, of course, on the scope and lifetime of the data -- does it apply to the whole application or just this instance? The best way, of course, is to make it an instance property like above, and I assume this will work, but if you're recreating the object you will have to use a different technique.
If you really do want to read the file again (because the data is from a different line), you will need to re-use the stream or, again, read all of the data in one go -- if possible -- then iterate through the items you've read internally.