im using a lot of streamwrtier in my application, and this one is suppsoed to log errors that happens while the program is running but at the moment it only creates the file withour writing into it :
if(File.Exists(currentLog))//currentLog = "Path\\Log.txt"
{
using (var fileStream = File.Open(currentLog,FileMode.Open))
{
StreamWriter ErreurStreamWriter = new StreamWriter(fileStream);
ErreurStreamWriter.WriteLine("{0}",e.Message);
ErreurStreamWriter.WriteLine("-------------------------------");
}
}
else
{
using (var fileStream = File.Create(currentLog))
{
StreamWriter ErreurStreamWriter = new StreamWriter(fileStream);
ErreurStreamWriter.Write("Liste des erreurs :");
ErreurStreamWriter.WriteLine("{0}", e.Message);
ErreurStreamWriter.WriteLine("-------------------------------");
}
}
Am I missing something obvious here ? Any help would be great, thanks
may be need to Flush() after write, or try to append when exist
Try this
using (var fileStream = File.Open(currentLog, FileMode.Open))
{
using (StreamWriter erreurStreamWriter = new StreamWriter(fileStream))
{
erreurStreamWriter.WriteLine("{0}", e.Message);
erreurStreamWriter.WriteLine("-------------------------------");
}
}
Basically what I think happens is that the stream writer never flush into the filestream.
Related
Having some problems with CsvHelper and writing to a memory stream. I've tried flushing the stream writer and setting positions and everything else tried. I figure I've narrowed it down to a really simple test case that obviously fails. What am I doing wrong here?
public OutputFile GetTestFile()
{
using (var ms = new MemoryStream())
using (var sr = new StreamWriter(ms))
using (var csv = new CsvWriter(sr))
{
csv.WriteField("test");
sr.Flush();
return new OutputFile
{
Data = ms.ToArray(),
Length = ms.Length,
DataType = "text/csv",
FileName = "test.csv"
};
}
}
[TestMethod]
public void TestWritingToMemoryStream()
{
var file = GetTestFile();
Assert.IsFalse(file.Data.Length == 0);
}
Editing the correct answer in for people googling as this corrected code actually passes my test. I have no idea why writing to a StringWriter then converting it to bytes solves all the crazy flushing issues, but it works now.
using (var sw = new StringWriter())
using (var csvWriter = new CsvWriter(sw, config))
{
csvWriter.WriteRecords(records);
return Encoding.UTF8.GetBytes(sw.ToString());
}
Since CSVHelper is meant to collect several fields per row/line, it does some buffering itself until you tell it the current record is done:
csv.WriteField("test");
csv.NextRecord();
sr.Flush();
Now, the memstream should have the data in it. However, unless there is more processing elsewhere, the result in your OutputFile is wrong: Data will be byte[] not "text/csv". It seems like StringWriter would produce something more appropriate:
string sBuff;
using (StringWriter sw = new StringWriter())
using (CsvWriter csv = new CsvWriter(sw))
{
csv.WriteRecord<SomeItem>(r);
sBuff = sw.ToString();
}
Console.WriteLine(sBuff);
"New Item ",Falcon,7
I am working with IsolatedStorage in Windows Phone 7.5. I am trying to read some text from a file. But the debugger says the operation is not permitted on IsolatedStorageFileStream. Why?
//Read the file from the specified location.
fileReader = new StreamReader(new IsolatedStorageFileStream("info.dat", FileMode.Open, fileStorage));
//Read the contents of the file (the only line we created).
string textFile = fileReader.ReadLine();
//Write the contents of the file to the MEssageBlock on the page.
MessageBox.Show(textFile);
fileReader.Close();
UPD my new code
object _syncObject = new object();
lock (_syncObject)
{
using (var fileStorage = IsolatedStorageFile.GetUserStoreForApplication())
{
using (FileStream stream = new FileStream("/info.dat", FileMode.Open, FileAccess.Read, FileShare.Read))
{
using (var reader = new StreamReader(stream))
{
string textFile = reader.ReadLine();
MessageBox.Show(textFile);
}
}
}
}
}
Try this, it works for me: Hope it works for you too
String sb;
using (IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
{
if (myIsolatedStorage.FileExists(fileName))
{
StreamReader reader = new StreamReader(new IsolatedStorageFileStream(fileName, FileMode.Open, myIsolatedStorage));
sb = reader.ReadToEnd();
reader.Close();
}
if(!String.IsNullOrEmpty(sb))
{
MessageBox.Show(sb);
}
}
If this doesn't work, then maybe your file doesn't exist.
Normally when I've used isolated storage, I've done something like:
using (var stream = fileStorage.OpenFile("info.dat", FileMode.Open))
{
using (var reader = new StreamReader(stream))
{
...
}
}
... rather than calling the constructor directly on IsolatedStorageFileStream. I can't say for sure whether that'll sort it out, but it's worth a try...
Just a guess:
WP emulator will reset all Isolatd Storage contents when it's closed
if you used FileMode.Open with a path to a non existing file you'll get Operation not permited exception.
You can use fileStorage.FileExists() to check if the file is there or use FileMode.OpenOrCreate.
I've just started using filestream, and although I made the code work,- I would really like to make it pretty as well :) I have no idea where to place the using statements so I can skip the stream.Close(), and how to use try catch finally. here is my code, not the prettiest thing, but it works. The double filestream is used to clear the file.
Edit: sorry for posting that code snippet blush that was pretty bad :P I've posted my second try :)
internal static void SaveFileAsTxt()
{
FileStream streamer = new FileStream("Shipping2.txt", FileMode.Append, FileAccess.Write, FileShare.Write);
streamer.Close();
FileStream f = File.Open("Shipping2.txt", FileMode.Create);
f.Close();
StreamWriter writer = new StreamWriter("Shipping2.txt", true, Encoding.ASCII);
foreach (var shipment in _shipments)
{
string write = (shipment.Distance + ","+ shipment.Distance).ToString();
writer.WriteLine(write);
};
writer.Close();
}
//--------new code--------
internal static void SaveFileAsTxt()
{
if (File.Exists("Shipping2.txt"))
{
File.Delete("Shipping2.txt");
}
using (StreamWriter writer = new StreamWriter("Shipping2.txt", true, Encoding.ASCII))
{
foreach (var shipment in _shipments)
{
string write = (shipment.Duration + ","+ shipment.Distance).ToString();
writer.WriteLine(write);
}
}
}
You don't need to open the file more than once - and you're actually opening it three times at the moment. This should be fine; File.CreateText will truncate the file if it already exists, and create it otherwise:
// Are you *sure* you want to use ASCII? UTF-8 might be a better bet...
using (TextWriter writer = File.CreateText("Shipping2.txt", Encoding.ASCII))
{
foreach (var shipment in _shipments)
{
// Removed redundant ToString call, and elided local variable.
// Consider using a format string instead:
// writer.WriteLine("{0},{1}", shipment.Distance, shipment.Distance);
writer.WriteLine(shipment.Distance + "," + shipment.Distance);
}
// Removed empty statement (trailing semi-colon)
}
Now, you say you want to use try/catch/finally - but why? If you fail to write to the file, do you definitely want to "handle" the exception in this method, rather than letting it bubble up to the caller?
Firstly, I dont understand the use for so many streams but you can use using in a number of places:
internal static void SaveFileAsTxt()
{
using(var streamer = new FileStream("Shipping2.txt", FileMode.Append, FileAccess.Write, FileShare.Write))
{
}
using(var f = File.Open("Shipping2.txt", FileMode.Create))
{
}
using(var writer = new StreamWriter("Shipping2.txt", true, Encoding.ASCII))
{
foreach (var shipment in _shipments)
{
string write = (shipment.Distance + ","+ shipment.Distance).ToString();
writer.WriteLine(write);
};
}
}
You can skip two first FileStreams and just use StreamWriter, it will create a file for you :
// Single using
using (StreamWriter writer = new StreamWriter(
"Shipping2.txt",
true, // !!!
Encoding.ASCII))
{
foreach (var shipment in _shipments)
{
string write = (shipment.Distance + "," + shipment.Distance)
.ToString();
writer.WriteLine(write);
}
}
MSDN:
public StreamWriter(
string path,
bool append,
Encoding encoding
)
append
Type: System.Boolean Determines whether data is to be appended to the
file. If the file exists and append is false, the file is overwritten.
If the file exists and append is true, the data is appended to the
file. Otherwise, a new file is created.
EDIT: Regarding an updated question (second part)
You do not need to delete file manually, just specify append = false in constructor of StreamWriter and it will overwrite a file:
If the file exists and append is false, the file is overwritten
Right now, the code you have is equivalent to this:
internal static void SaveFileAsTxt() {
using (FileStream streamer = new FileStream(
"Shipping2.txt", FileMode.Append, FileAccess.Write, FileShare.Write
);) {}
using(FileStream f = File.Open("Shipping2.txt", FileMode.Create)) {}
using(StreamWriter writer =
new StreamWriter("Shipping2.txt", true, Encoding.ASCII)) {
foreach (var shipment in _shipments) {
string write = (shipment.Distance + "," + shipment.Distance).ToString();
writer.WriteLine(write);
}
}
}
But I don't know why you opened the first file.
In respect to the second, I believe you tried to create the file using this method,
but there are other ways to do that as well.
// Single using
using (StreamWriter writer = new StreamWriter(
"Shipping2.txt",
true, // !!!
Encoding.ASCII))
{
foreach (var shipment in _shipments)
{
string write = (shipment.Distance + "," + shipment.Distance)
.ToString();
writer.WriteLine(write);
}
}
Just to be different, I'll use LINQ :-)
File.WriteAllLines(
"Shipping2.txt",
_shipments.Select(
p => string.Format(
"{0},{1}",
shipment.Distance,
shipment.Distance)
),
Encoding.ASCII);
This version requires .NET 4.0. File.WriteAllLines will create the file, write all the lines and close the file. _shipments.Select(p => string.Format("{0},{1}", shipment.Distance, shipment.Distance)) will return, for each element of _shipments, a string containing shipment.Distance + "," + shipment.Distance (formatted using string.Format)
`
I have a windows service writes its log in a text file in a simple format.
Now, I'm going to create a small application to read the service's log and shows both the existing log and the added one as live view.
The problem is that the service locks the text file for adding the new lines and at the same time the viewer application locks the file for reading.
The Service Code:
void WriteInLog(string logFilePath, data)
{
File.AppendAllText(logFilePath,
string.Format("{0} : {1}\r\n", DateTime.Now, data));
}
The viewer Code:
int index = 0;
private void Form1_Load(object sender, EventArgs e)
{
try
{
using (StreamReader sr = new StreamReader(logFilePath))
{
while (sr.Peek() >= 0) // reading the old data
{
AddLineToGrid(sr.ReadLine());
index++;
}
sr.Close();
}
timer1.Start();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void timer1_Tick(object sender, EventArgs e)
{
using (StreamReader sr = new StreamReader(logFilePath))
{
// skipping the old data, it has read in the Form1_Load event handler
for (int i = 0; i < index ; i++)
sr.ReadLine();
while (sr.Peek() >= 0) // reading the live data if exists
{
string str = sr.ReadLine();
if (str != null)
{
AddLineToGrid(str);
index++;
}
}
sr.Close();
}
}
Is there any problem in my code in reading and writing way?
How to solve the problem?
You need to make sure that both the service and the reader open the log file non-exclusively. Try this:
For the service - the writer in your example - use a FileStream instance created as follows:
var outStream = new FileStream(logfileName, FileMode.Open,
FileAccess.Write, FileShare.ReadWrite);
For the reader use the same but change the file access:
var inStream = new FileStream(logfileName, FileMode.Open,
FileAccess.Read, FileShare.ReadWrite);
Also, since FileStream implements IDisposable make sure that in both cases you consider using a using statement, for example for the writer:
using(var outStream = ...)
{
// using outStream here
...
}
Good luck!
Explicit set up the sharing mode while reading the text file.
using (FileStream fs = new FileStream(logFilePath,
FileMode.Open,
FileAccess.Read,
FileShare.ReadWrite))
{
using (StreamReader sr = new StreamReader(fs))
{
while (sr.Peek() >= 0) // reading the old data
{
AddLineToGrid(sr.ReadLine());
index++;
}
}
}
new StreamReader(File.Open(logFilePath,
FileMode.Open,
FileAccess.Read,
FileShare.ReadWrite))
-> this doesn't lock the file.
The problem is when you are writing to the log you are exclusively locking the file down so your StreamReader won't be allowed to open it at all.
You need to try open the file in readonly mode.
using (FileStream fs = new FileStream("myLogFile.txt", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
using (StreamReader sr = new StreamReader(fs))
{
while (!fs.EndOfStream)
{
string line = fs.ReadLine();
// Your code here
}
}
}
I remember doing the same thing a couple of years ago. After some google queries i found this:
FileStream fs = new FileStream(#”c:\test.txt”,
FileMode.Open,
FileAccess.Read,
FileShare.ReadWrite);
i.e. use the FileShare.ReadWrite attribute on FileStream().
(found on Balaji Ramesh's blog)
Have you tried copying the file, then reading it?
Just update the copy whenever big changes are made.
This method will help you to fastest read a text file and without locking it.
private string ReadFileAndFetchStringInSingleLine(string file)
{
StringBuilder sb;
try
{
sb = new StringBuilder();
using (FileStream fs = File.Open(file, FileMode.Open))
{
using (BufferedStream bs = new BufferedStream(fs))
{
using (StreamReader sr = new StreamReader(bs))
{
string str;
while ((str = sr.ReadLine()) != null)
{
sb.Append(str);
}
}
}
}
return sb.ToString();
}
catch (Exception ex)
{
return "";
}
}
Hope this method will help you.
In C#, if I want to deterministically clean up non-managed resources, I can use the "using" keyword. But for multiple dependent objects, this ends up nesting further and further:
using (FileStream fs = new FileStream("c:\file.txt", FileMode.Open))
{
using (BufferedStream bs = new BufferedStream(fs))
{
using (StreamReader sr = new StreamReader(bs))
{
// use sr, and have everything cleaned up when done.
}
}
}
In C++, I'm used to being able to use destructors to do it like this:
{
FileStream fs("c:\file.txt", FileMode.Open);
BufferedStream bs(fs);
StreamReader sr(bs);
// use sr, and have everything cleaned up when done.
}
Is there a better way in C# to do this? Or am I stuck with the multiple levels of nesting?
You don't have to nest with multiple usings:
using (FileStream fs = new FileStream("c:\file.txt", FileMode.Open))
using (BufferedStream bs = new BufferedStream(fs))
using (StreamReader sr = new StreamReader(bs))
{
// all three get disposed when you're done
}
In .NET Core, there's a new using statement which allows you to dispense with the parentheses, and the disposal happens at the end of the current scope:
void MyMethod()
{
using var fs = new FileStream("c:\file.txt", FileMode.Open);
using var bs = new BufferedStream(fs);
using var sr = new StreamReader(bs);
// all three are disposed at the end of the method
}
You can put using statements together before the opening braces like so:
using (StreamWriter w1 = File.CreateText("W1"))
using (StreamWriter w2 = File.CreateText("W2"))
{
// code here
}
http://blogs.msdn.com/ericgu/archive/2004/08/05/209267.aspx
You could use this syntax to condense things down a bit:
using (FileStream fs = new FileStream("c:\file.txt", FileMode.Open))
using (BufferedStream bs = new BufferedStream(fs))
using (StreamReader sr = new StreamReader(bs))
{
}
This is one of those rare occasions where not using { } for all blocks makes sense IMHO.
I have implemented solutions like Michael Meadows's before, but his StreamWrapper code doesn't take into account if the Dispose() methods called on the member variables throw an exception for one reason or another, the subsequent Dispose()es will not be called and resources could dangle. The safer way for that one to work is:
var exceptions = new List<Exception>();
try
{
this.sr.Dispose();
}
catch (Exception ex)
{
exceptions.Add(ex);
}
try
{
this.bs.Dispose();
}
catch (Exception ex)
{
exceptions.Add(ex);
}
try
{
this.fs.Dispose();
}
catch (Exception ex)
{
exceptions.Add(ex);
}
if (exceptions.Count > 0)
{
throw new AggregateException(exceptions);
}
}
Instead of nesting using statements, you can just write out the .Dispose calls manually - but you'll almost certainly miss one at some point.
Either run FxCop or something else that can make sure that all IDisposable-implementing type instances have a .Dispose() call, or deal with the nesting.
you can omit the curly braces, like:
using (FileStream fs = new FileStream("c:\file.txt", FileMode.Open))
using (BufferedStream bs = new BufferedStream(fs))
using (StreamReader sr = new StreamReader(bs))
{
// use sr, and have everything cleaned up when done.
}
or use the regular try finally approach:
FileStream fs = new FileStream("c:\file.txt", FileMode.Open);
BufferedStream bs = new BufferedStream(fs);
StreamReader sr = new StreamReader(bs);
try
{
// use sr, and have everything cleaned up when done.
}finally{
sr.Close(); // should be enough since you hand control to the reader
}
This makes for a much larger net plus in lines of code, but a tangible gain in readability:
using (StreamWrapper wrapper = new StreamWrapper("c:\file.txt", FileMode.Open))
{
// do stuff using wrapper.Reader
}
Where StreamWrapper is defined here:
private class StreamWrapper : IDisposable
{
private readonly FileStream fs;
private readonly BufferedStream bs;
private readonly StreamReader sr;
public StreamWrapper(string fileName, FileMode mode)
{
fs = new FileStream(fileName, mode);
bs = new BufferedStream(fs);
sr = new StreamReader(bs);
}
public StreamReader Reader
{
get { return sr; }
}
public void Dispose()
{
sr.Dispose();
bs.Dispose();
fs.Dispose();
}
}
With some effort, StreamWrapper could be refactored to be more generic and reusable.
It should be noted that generally when creating stream based off another stream the new stream will close the one being passed in. So, to further reduce your example:
using (Stream Reader sr = new StreamReader( new BufferedStream( new FileStream("c:\file.txt", FileMode.Open))))
{
// all three get disposed when you're done
}
for this example let us assume you have:
a file named 1.xml under c:\
a textbox named textBox1, with the multi-line properties set ON.
const string fname = #"c:\1.xml";
StreamReader sr=new StreamReader(new BufferedStream(new FileStream(fname,FileMode.Open,FileAccess.Read,FileShare.Delete)));
textBox1.Text = sr.ReadToEnd();
The using statement is syntactic sugar that converts to:
try
{
obj declaration
...
}
finally
{
obj.Dispose();
}
You can explicitly call Dispose on your objects, but it won't be as safe, since if one of them throws an exception, the resources won't be freed properly.