I've got a windows form with save/loading of XML files and it asks the user where they want to save/load it. My problem is I dont know how to change this method to load the file from where the user wants and not where the streamreader specifies.
The code below is of my button and LoadValues Method.
private void Edittask_loadbuttonClick(
object sender, EventArgs e)
{
Stream myStream = null;
var sFile1 = new OpenFileDialog();
sFile1.InitialDirectory = "c:\\";
sFile1.Filter = "xml files (*.xml)|*.xml";
sFile1.FilterIndex = 2;
sFile1.RestoreDirectory = true;
if (sFile1.ShowDialog() == DialogResult.OK)
{
try
{
if ((myStream = sFile1.OpenFile()) != null)
{
using (myStream)
{
var v = LoadValues();
this.load_task1_name.Text =
v.task1_name;
this.load_task1_desc.Text =
v.task1_desc;
this.load_task1_date.Value =
v.task1_date;
this.load_checkbox.Checked =
v.task1_checkbox;
}
}
}
catch (Exception ex)
{
MessageBox.Show(
"Error: Could not read file from disk. Original error: " +
ex.Message);
}
}
}
public Values LoadValues()
{
var serializer = new XmlSerializer(typeof (Values));
using (
TextReader textReader = new StreamReader(
"E:\\hello.xml")
)
{
return
(Values) serializer.Deserialize(textReader);
}
}
I would pass the Stream from the OpenFileDialog to LoadValues(...), and use that to construct your StreamReader:
public Values LoadValues(Stream stream)
{
XmlSerializer serializer = new XmlSerializer(typeof(Values));
using (TextReader textReader = new StreamReader(stream))
{
return (Values)serializer.Deserialize(textReader);
}
}
and
if ((myStream = sFile1.OpenFile()) != null)
{
using (myStream)
{
Values v = LoadValues(myStream);
...
}
}
You need to pass the Stream as a parameter to your function.
Related
**sorry for my english but i don't know very well in google translate i do translation.
I want from my listbox the file that I choose to be exported with the same name that it has in my listbox**
private void downloadFile(object sender, EventArgs e)
{
string ip = txt_ip.Text;
string user = txt_user.Text;
string pass = txt_pass.Text;
//string pathLocalFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "download_sftp_file.txt");
try
{
SftpClient client = new SftpClient(ip, user, pass);
client.Connect();
string rmDer = dr_finder.Text;
var files = client.ListDirectory(rmDer);
if (rmDer == "")
{
client.Connect();
string rmDerNow = "/";
var filesName = client.ListDirectory(rmDerNow);
foreach (var file in filesName)
{
DirList.Items.Add(file.Name);
string result = Path.GetFileNameWithoutExtension(file.Name);
DirList.Items.Add(System.IO.Path.GetFileName(file.Name));
}
MessageBox.Show("List Directory Success!");
}
string pachRemFile = DirList.SelectedItem.ToString();
string pachlocalFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop),"Server Ftp File.txt");
Stream Filestream = File.OpenWrite(pachlocalFile);
client.DownloadFile(pachRemFile,Filestream);
client.Disconnect();
}
catch (Exception error)
{
MessageBox.Show(error.Message);
}
}
this object is the solution I finally didn't find anyone to help me. so I helped myself.
and I thought he had good programmers on this site
SaveFileDialog savefile = new SaveFileDialog(); /* this here is my solution get a save as. */
if (savefile.ShowDialog() == DialogResult.OK)
{
string pachRemFile = DirList.SelectedItem.ToString();
Stream Filestream = File.Open(savefile.FileName, FileMode.CreateNew);
StreamWriter sw = new StreamWriter(Filestream);
client.DownloadFile(pachRemFile, Filestream);
client.Disconnect();
}
I'm trying to create a simple logging tool to monitor file changes. I have used the FileSystemWatcher to detect changes to the file, but I've discovered that the events are only triggered when the file is closed, not when the buffer is flushed. This means that if multiple lines are added before the file is closed, I will only see that when the file is closed.
here is my test example.
[TestClass]
public class FileWriteTests
{
[TestMethod]
public void TestMethodAfterClose()
{
var currentDir = Environment.CurrentDirectory;
var fileToMonitor = "test.txt";
List<string> output = new List<string>();
var watcherTest = new FileWatcherTest(fileToMonitor, currentDir, output);
File.Delete(Path.Combine(currentDir, fileToMonitor));
using (var writer = new StreamWriter(Path.Combine(currentDir, fileToMonitor), true))
{
writer.WriteLine($"test");
writer.Flush();
}
System.Threading.Thread.Sleep(10);
Assert.AreEqual(1, output.Count);
Assert.AreEqual("test", output[0]);
}
[TestMethod]
public void TestMethodAfterFlush()
{
var currentDir = Environment.CurrentDirectory;
var fileToMonitor = "test.txt";
List<string> output = new List<string>();
var watcherTest = new FileWatcherTest(fileToMonitor, currentDir, output);
File.Delete(Path.Combine(currentDir, fileToMonitor));
using (var writer = new StreamWriter(Path.Combine(currentDir, fileToMonitor), true))
{
try
{
writer.WriteLine($"test");
writer.Flush();
System.Threading.Thread.Sleep(1000);
// add break point here for BareTail
Assert.AreEqual(1, output.Count);
Assert.AreEqual("test", output[0]);
}
catch
{
Assert.Fail("Test failed");
}
}
}
public class FileWatcherTest
{
public string FileName { get; set; }
public string Directory { get; set; }
private List<string> linesRead;
private FileSystemWatcher watcher;
public FileWatcherTest(string fileName, string directory, List<string> output)
{
FileName = fileName;
Directory = directory;
linesRead = output;
watcher = new FileSystemWatcher();
watcher.Path = directory;
watcher.Filter = FileName;
watcher.Changed += Watcher_Changed;
watcher.EnableRaisingEvents = true;
watcher.NotifyFilter = NotifyFilters.Attributes |
NotifyFilters.CreationTime |
NotifyFilters.DirectoryName |
NotifyFilters.FileName |
NotifyFilters.LastAccess |
NotifyFilters.LastWrite |
NotifyFilters.Security |
NotifyFilters.Size;
}
private void Watcher_Changed(object sender, FileSystemEventArgs e)
{
using (var fileStream = File.Open(Path.Combine(Directory, FileName), FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete | FileShare.Inheritable))
{
using (var reader = new StreamReader(fileStream))
{
string line;
while ((line = reader.ReadLine()) != null)
{
linesRead.Add(line);
}
}
}
}
}
}
right now TestMethodAfterClose succeeds and TestMethodAfterFlush fails. When I use the program BareTail and wait at the breakpoint, I see that it updates the display before the file is closed. So that gives me an indication that it's possible. I don't know if it's possible in C# and I might need to import some native functions using dllimport. The problem is I don't know where to look
How do I make both tests succeed, while not using a timer?
EDIT:
updated the FileWatcherTest class
Unfortunately Flush doesn't flush the thing you want. I find a lot articles to explain it, for example:
https://blogs.msdn.microsoft.com/alejacma/2011/03/23/filesystemwatcher-class-does-not-fire-change-events-when-notifyfilters-size-is-used/
There is a solution since .net 4, use another overload method of FileStream: Flush(bool)
var fs = writer.BaseStream as FileStream;
fs.Flush(true);
And you only give disk 10ms to react, maybe this is another problem.
After some searching, I discovered that the FileSystemWatcher only triggers an event after a file is closed as shown in this article. The article only mentions the date modified NotifyFilter, but in my testing I found that all Notifyfilters trigger after the file is closed and never while it's still open.
For that reason, it looks like tailing a file is only possible with a looped function that continuously monitors the file for extra rows. I used the code on this link as an example.
Here is my code working:
[TestClass]
public class FileWriteTests
{
[TestMethod]
public void TestMethodAfterClose_filetailing()
{
var currentDir = Environment.CurrentDirectory;
var fileToMonitor = "test.txt";
File.Delete(Path.Combine(currentDir, fileToMonitor));
List<string> output = new List<string>();
using (var watcherTest = new PersonalFileTail(currentDir, fileToMonitor))
{
watcherTest.StartTail(delegate (string line) { output.Add(line); });
using (var writer = new StreamWriter(Path.Combine(currentDir, fileToMonitor), true))
{
writer.WriteLine($"test");
writer.Flush();
}
System.Threading.Thread.Sleep(200);
watcherTest.StopTail();
}
System.Threading.Thread.Sleep(10);
Assert.AreEqual(1, output.Count);
Assert.AreEqual("test", output[0]);
}
[TestMethod]
public void TestMethodAfterFlush_filetailing()
{
// initiate file
var currentDir = Environment.CurrentDirectory;
var fileToMonitor = "test.txt";
File.Delete(Path.Combine(currentDir, fileToMonitor));
FileInfo info = new FileInfo(Path.Combine(currentDir, fileToMonitor));
List<string> output = new List<string>();
using (var watcherTest = new PersonalFileTail(currentDir, fileToMonitor))
{
watcherTest.StartTail(delegate (string line) { output.Add(line); });
using (var writer = new StreamWriter(Path.Combine(currentDir, fileToMonitor), true))
{
try
{
writer.WriteLine($"test");
writer.Flush();
System.Threading.Thread.Sleep(1000);
Assert.AreEqual(1, output.Count);
Assert.AreEqual("test", output[0]);
}
catch
{
Assert.Fail("Test failed");
}
}
watcherTest.StopTail();
}
}
public class PersonalFileTail : IDisposable
{
private string filename;
private string directory;
private Task fileTailTask;
private Action<string> handleResults;
private volatile bool runTask;
private long lastFilePosition;
public string FileName
{
get { return Path.Combine(directory, filename); }
}
public PersonalFileTail(string directory, string filename)
{
this.directory = directory;
this.filename = filename;
this.runTask = false;
lastFilePosition = 0;
}
public void StartTail(Action<string> handleResults)
{
this.handleResults = handleResults;
runTask = true;
fileTailTask = Task.Run(() => MonitorFileTask());
}
public void StopTail()
{
runTask = false;
fileTailTask.Wait();
}
public IEnumerable<string> ReadLinesFromFile()
{
using (StreamReader reader = new StreamReader(new FileStream(FileName,
FileMode.Open, FileAccess.Read, FileShare.ReadWrite)))
{
string line = "";
while ((line = reader.ReadLine()) != null)
{
yield return line;
}
lastFilePosition = reader.BaseStream.Length;
}
}
public void MonitorFileTask()
{
StreamReader reader = null;
FileStream stream = null;
try
{
using(stream = new FileStream(FileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (reader = new StreamReader(stream))
{
do
{
//if the file size has increased do something
if (reader.BaseStream.Length > lastFilePosition)
{
//seek to the last max offset
reader.BaseStream.Seek(lastFilePosition, SeekOrigin.Begin);
//read out of the file until the EOF
string line = "";
while ((line = reader.ReadLine()) != null)
{
handleResults(line);
}
//update the last max offset
lastFilePosition = reader.BaseStream.Position;
}
// sleep task for 100 ms
System.Threading.Thread.Sleep(100);
}
while (runTask);
}
}
catch
{
if (reader != null)
reader.Dispose();
if (stream != null)
stream.Dispose();
}
}
public void Dispose()
{
if(runTask)
{
runTask = false;
fileTailTask.Wait();
}
}
}
}
If anyone knows a way in which tailing can be done without using a timed function, I will accept that as the answer. Until that time, i feel that my answer is the only possible way to do this.
Here is my code. I can't seem to use the openFileDialog with the way I used the StreamReader? Any ideas please.
StreamReader reader = null;
OpenFileDialog openFileDialog1 = new OpenFileDialog();
openFileDialog1.InitialDirectory = "c:\\";
openFileDialog1.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*";
openFileDialog1.FilterIndex = 2;
openFileDialog1.RestoreDirectory = true;
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
try
{
if ((reader = openFileDialog1.OpenFile()) != null)
{
using (reader)
{
textBox2.Text = reader.ReadLine();
textBox3.Text = reader.ReadLine();
}
}
}
catch (Exception ex)
{
MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message);
}
}
Thank you.
OpenFileDialog.OpenFile() returns a Stream:
if ((var stream = openFileDialog1.OpenFile()) != null)
{
using (var reader = new StreamReader(stream))
{
// ...
}
}
Alternatively, so you can omit obtaining the stream manually and ugly null-check following it (will it return null anytime, or rather throw an exception?):
using (reader = new StreamReader(openFileDialog1.Filename))
{
// ...
}
When I try to open a .txt file it only shows its location in my textbox.
I am out of ideas:( hope you can help me...
code:
private void OpenItem_Click(object sender, EventArgs e)
{
openFileDialog1.ShowDialog();
System.IO.StringReader OpenFile = new System.IO.StringReader(openFileDialog1.FileName);
richTextBox1.Text = OpenFile.ReadToEnd();
OpenFile.Close();
}
A StringReader reads the characters from the string you pass to it -- in this case, the file's name. If you want to read the contents of the file, use a StreamReader:
var OpenFile = new System.IO.StreamReader(openFileDialog1.FileName);
richTextBox1.Text = OpenFile.ReadToEnd();
Use File.ReadAllText
richTextBox1.Text = File.ReadAllText(openFileDialog1.FileName);
I'd use the File.OpenText() method for reading text-files. You should also use using statements to properly dispose the object.
if(openFileDialog1.ShowDialog() == DialogResult.OK)
{
try
{
// Make sure a file was selected
if ((myStream = openFileDialog1.OpenFile()) != null) {
// Open stream
using (StreamReader sr = File.OpenText(openFileDialog1.FileName))
{
// Read the text
richTextBox1.Text = sr.ReadToEnd();
}
}
}
catch (Exception ex)
{
MessageBox.Show("An error occured: " + ex.Message);
}
}
That's easy. This is what you need to do:
1) Put using System.IO; above namespace.
2) Create a new method:
public static void read()
{
StreamReader readme = null;
try
{
readme = File.OpenText(#"C:\path\to\your\.txt\file.txt");
Console.WriteLine(readme.ReadToEnd());
}
// will return an invalid file name error
catch (FileNotFoundException errorMsg)
{
Console.WriteLine("Error, " + errorMsg.Message);
}
// will return an invalid path error
catch (Exception errorMsg)
{
Console.WriteLine("Error, " + errorMsg.Message);
}
finally
{
if (readme != null)
{
readme.Close();
}
}
}
3) Call it in your main method: read();
4) You're done!
i have the following code used to serialize a label's content. When i press the "save" button, an xml file is generated. When press the "load" button after i select the same xml file, an error occured, IOexception was unhandled, The process cannot access the file 'C:\datasaved.xml' because it is being used by another process. Is there anything wrong with my code?
Thanks.
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();
FileStream 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;
}
}
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;
FileStream loadstream = new FileStream(loadpath, FileMode.Open);
XmlSerializer serializer = new XmlSerializer(typeof(FormSaving));
abc = (FormSaving)serializer.Deserialize(loadstream);
loadstream.Close();
MajorversionresultLabel.Content = abc.Majorversion;
}
This is the most immediate problem:
FileStream savestream = new FileStream(savepath, FileMode.Create);
XmlSerializer serializer = new XmlSerializer(typeof(FormSaving));
serializer.Serialize(savestream, abc);
You're not closing the stream, so the file can't be reopened for read. Use a using statement:
using (Stream savestream = new FileStream(savepath, FileMode.Create))
{
XmlSerializer serializer = new XmlSerializer(typeof(FormSaving));
serializer.Serialize(savestream, abc);
}
You should take the same approach when loading the file as well, instead of calling Close explicitly... with your current code, if an exception occurs when deserializing, you won't be closing the stream.
You're also opening the file via Dialog.OpenFile, but not closing that stream... and why bother opening it twice? Just read from the stream you've opened.
Finally (for the moment) you're catching an exception (blindly, with no regard for which exceptions are really worth trying to handle) but then continuing regardless. If you've caught an exception, chances are the last part of the method won't execute correctly, so you should either return or throw another exception yourself.