My program is logging data to a file, at the same time a user interface displays the incoming data live. I want the logged data to be on disk within a second or two if computer/program/os/whatever shuts down. Data is coming in at least 100 times/sec.
I want the user to be able to give the log-file a new name, while logging is active. The problem is that i can't change the name of the file while it is open, even if it is by the same process.
Test case:
string fileName1 = "test.txt";
string fileName2 = "test2.txt";
using (StreamWriter sw = new StreamWriter(new FileStream(fileName1, FileMode.Create)))
{
sw.WriteLine("before");
File.Move(fileName1, fileName2); //<<-- IOException - The process cannot access the file because it is being used by another process.
w.WriteLine("after");
}
So, How do i rename a file from a process while the same process is having a stream to the file open?
You should close the first stream, rename the file, then reopen the stream:
using (StreamWriter sw = new StreamWriter(new FileStream(fileName1, FileMode.Create)))
{
sw.WriteLine("before");
sw.Close();
}
File.Move(fileName1, fileName2);
using (StreamWriter sw = new StreamWriter(new FileStream(fileName2, FileMode.Append)))
{
sw.WriteLine("after");
}
I know this answer is a bit late to help you on your porting project but perhaps it will help others!
If you open the file with the FileShare.Delete flag it will let you rename it even though it is still open :)
You can't rename a file while it is open by a process, but if you want to write to it from the other instance of your program, do this.
Try FileShare.Write. You can use it in File.Open.
using (StreamWriter sw = new StreamWriter (File.Open(path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Write))
{
...
}
Opening en closing the file 100 times a second will have a impact on your performance, you can log to a temp file and append the temp file every 10 seconds or so. That will give you what you want.
Related
I have Simple console application and list of files.
Every loop over my list i want to write the current file name into simple txt file:
String path = #"C:\log.txt"; // location whre to save my txt file
List<string> files = new List<string>(); // my files list
using (FileStream fs = new FileStream(path, FileMode.Append, FileAccess.Write))
using (StreamWriter sw = new StreamWriter(fs))
{
foreach (string file in files)
{
sw.WriteLine(file);
}
}
Why i can see the lines that written only at the end of my loop ?
What would happen if my application will crash at the middle of the loop ? my log files will be empty ?
StreamWriter buffers its output for performance reasons. It will write to the file if there are enough bytes in the internal buffer, if you call Flush()or if the stream is closed / disposed.
If you want your output to show immediately you'll have to add a call to sw.Flush() after each line written to sw.
Why i can see the lines that written only at the end of my loop.
Because the file is only being flushed to disk once StreamWriter.Dispose runs, at the end of your using statement. Meanwhile, it is buffered in memory.
What would happen if my application will crash at the middle of the
loop ? my log files will be empty ?
That depends on when your program terminated and what state the stream was at in that particular moment. If it was able to finish and flush to disk, you'll see the log file.
If you're afraid this piece of code might cause your application to crash due to some expected error, wrap your code in a try-catch block, and handle those exceptions.
So i have my write to file function and it will create the file if it does not exist, and it works but the problem is first time you run the code when the file does not exist it creates it and then crash the program
//writing file to Error.txt
string path = #err;
if (!File.Exists(path)) // if does not exist make it
{
File.Create(path);
TextWriter tw = new StreamWriter(path); //crashes here after create
tw.WriteLine(i);
tw.Close();
}
Exception is:
An unhandled exception of type 'System.IO.IOException' occurred in mscorlib.dll
Additional information: The process cannot access the file
'C:\Users\Desktop\TestStuff\error.txt' because it is being used by another process.
You're using 2 file streams here without closing the first one.
get rid of File.Create(path);. That method creates a file, but it also returns a file stream which you're not storing and closing.
StreamWriter will make the file for you, but it can't, because your program has a handle on it.
You could make it easier by just using
using (TextWriter tw = new StreamWriter(path, FileMode.Create, FileAccess.Write))
{
tw.WriteLine(i);
}
This would create, or reopen the file from position 0, and you can write to it like that
So basically I write a windows service that scans any given directory for a zip file and then uploads it to an FTP server. I added a tracing method that suppose to write into a txt file and keep a log of everything. The problems comes when I release the service into windows I get a error message in the Event Viewer( I added a LogEvent using EventLog class) that returns
System.IO.IOException: The process cannot access the file
'C:\Windows\system32\traceLog.txt' because it is being used by another
process.
The code that does the tracing is the following
private void EscribirTrace(string mensaje)
{
if (Tracing)
{
try
{
using (FileStream archivo2 = new FileStream(string.Format("{0}\\traceLog.txt", Environment.CurrentDirectory), FileMode.Append, FileAccess.Write, FileShare.ReadWrite))
{
mensaje = string.Format("{0} - {1} \r\n", DateTime.Now, mensaje);
StreamWriter writer = new StreamWriter(archivo2);
writer.WriteLine(mensaje);
writer.Flush();
writer.Dispose();
}
}
catch (Exception ex)
{
LogEvent("Error en escribir tracing", ex);
}
}
}
Any ideas would be appreciated
Edit So after some research I figure that that system32 is not the best place for the file. My intention was to have that log file at the path were the service was installed. After some research I replaced the
Enviroment.CurrentDirectory
for
Path.GetFullPath(System.Reflection.Assembly.GetExecutingAssembly().Location).Replace(
Path.GetFileName(System.Reflection.Assembly.GetExecutingAssembly().Location)
Formated into a string.
The rest just worked pretty well.
Thank you for the responses !
Its because your using statement has not released the file yet. You have it open in the steam so you can't write to it until you close your stream.
If you want to simply write text to a file just use:
File.WriteAllText(FILEPATH, TEXTDATA);
That call will open the file, write to it, and then close it.
if it throws on the using ...make sure all other streams on the file are closed properly ...
if it throws on the streamwriter constructor
change the using to be the stream writer with the new filestream in the constructor
/Windows/system32 requires admin access. Your application probably isn't running with the proper privileges. You should try writing the log to a different (less restrictive) location. If you need to write to system32 ensure that your service is running with admin privileges.
I am trying to open a file, but I received:
The process cannot access the file because it is being used by another process. The File is an XML-Document. Can anyone help?
string activeDirectory = #"X:\SubGraph\";
string[] files = Directory.GetFiles(activeDirectory);
foreach (string fileName in files){
FileStream file = new FileStream(fileName, FileMode.Open, FileAccess.Read);
After using a file, you must to close it, I think:
foreach (string fileName in files)
{
FileStream file = new FileStream(fileName, FileMode.Open, FileAccess.Read);
//your code
file.Close();
}
If you are using this piece of code in some kind of loop you need to close your FileStream each time before finishing loop cycle.
file.Close();
Or use "using" construction like this:
using (FileStream file = new FileStream(fileName, FileMode.Open, FileAccess.Read))
{
// your code goes here
file.Close();
}
Moreover, you better to accustom yourself to close all manually created streams after they are unnecessary anymore.
Under some circumstances Windows locks the files. In your case can be:
Another process is locking the file. It might be windows or you av software or who knows.
In order to discover who is locking the file you might several tools like wholockme or Unlocker. These tools will tell you which process is locking the file and even allow you to unlock it.
Maybe you are locking your own file. In your code snippet seems you are not closing the file you are reading (Maybe you can edit your question and add all code). You should remember to include:
file.Close();
... or file will remain open.
IsolatedStorageFile iF = IsolatedStorageFile.GetUserStoreForApplication();
if (!iF.DirectoryExists("aaa"))
{
MessageBox.Show("No directory, create!");
iF.CreateDirectory("aaa");
}
StreamWriter fW = new StreamWriter(new IsolatedStorageFileStream("girls\\list.txt", FileMode.OpenOrCreate, iF));
fW.WriteLine(this.tb_name.Text);
So, I create file, or open it, and add to it content of textbox. I need append this file, but it rewrites. Please, help me to solve this problem :) Thank you!
You want FileMode.Append, not FileMode.OpenOrCreate
See this page for details http://msdn.microsoft.com/en-us/library/system.io.filemode(v=vs.95).aspx
Append: Opens the file if it exists and seeks to the end of the file, or
creates a new file.
Use FileMode.Append for if it exists, FileMode.Create if it does not.