I am getting this error: The process cannot access the file (...) because it is being used by another process.
I have tried to use
File.WriteAllText;
StreamWriter sw = new StreamWriter(myfilepath);
sw.Write(mystring);
sw.Close();
sw.Dispose();
;
using (FileStream fstr = File.Create(myfilepath))
{
StreamWriter sw = new StreamWriter(myfilepath);
sw.Write(mystring);
sw.Close();
sw.Dispose();
fstr.Close();
}
All I am trying to do is to access a file, write on it, then close it. I might be making a silly mistake but I would like to understand what I am doing wrong and why. How to make sure that the file is closed and not to cause this error again.
Helped by the answers so far I did this:
using (FileStream fstr = File.Open(myfilepath,FileMode.OpenOrCreate,FileAccess.ReadWrite))
{
StreamWriter sw = new StreamWriter(fstr);
sw.Write(mystring);
sw.Close();
}
It seems to be better because it seems to close/stop the process of my file if I try to access another file on the second time I access the page. But if I try to access the same file on a second time, it gives me the error again.
Why not just use:
System.IO.File.WriteAllText(myfilepath, mystring");
That should not lock your file.
Internally WriteAllText uses FileShare.Read and releases that lock as soon as it is done writing.
"because it is being used by another process" that's the clue. Do you by chance have the file open in Notepad or something?
You may need to set the sharing mode when you open the file to allow readers, and ask only for the permission you need (write access).
http://msdn.microsoft.com/en-us/library/5h0z48dh.aspx
I would like to thank everyone for the help.
In fact, apart from this code I found out that I had a stremReader still opened somewhere else after the code above. At the end I changed the code I had before for this:
using (FileStream fstr = File.Open(myfile, FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
StreamWriter sw = new StreamWriter(fstr);
sw.Write(mystring);
sw.Flush();
sw.Dispose();
}
and on my StreamReader I did this:
StreamReader sr = new StreamReader(myfile);
string sometext = sr.ReadToEnd();
sr.Dispose();
I could also use this:
File.ReadAllText(myfile);
If there is something that I could have done in a better way please tell me.
Thank you very much.
Try this
FileStream fs = new FileStream(myfilepath, FileMode.Create, FileAccess.Write);
byte[] bt = System.Text.Encoding.ASCII.GetBytes(mystring);
fs.Write(bt, 0, bt.Length);
fs.Close();
Related
I'm attempting to use StreamReader and StreamWriter to grab a temporary output log (.txt format) from another application.
The output log is always open and constantly written to.
Unhelpfully if the application closes or crashes, the log file ends up deleted - hence the need for a tool that can grab the information from this log and save it.
What my program currently does is:
Create a new .txt file, and stores the path of that file as the
string "destinationFile".
Finds the .txt log file to read, and stores the path of that file as
the string "sourceFile"
It then passes those two strings to the method below.
Essentially I'm trying to read the sourceFile one line at a time.
Each time one line is read, it is appended to destinationFile.
This keeps looping until the sourceFile no longer exists (i.e. the application has closed or crashed and deleted its log).
In addition, the sourceFile can get quite big (sometimes 100Mb+), and this program may be handling more than one log at a time.
Reading the whole log rather than line by line will most likely start consuming a fair bit of memory.
private void logCopier(string sourceFile, string destinationFile)
{
while (File.Exists(sourceFile))
{
string textLine;
using (var readerStream = File.Open(sourceFile,
FileMode.Open,
FileAccess.Read,
FileShare.ReadWrite))
using (var reader = new StreamReader(readerStream))
{
while ((textLine = reader.ReadLine()) != null)
{
using (FileStream writerStream = new FileStream(destinationFile,
FileMode.Append,
FileAccess.Write))
using (StreamWriter writer = new StreamWriter(writerStream))
{
writer.WriteLine(textLine);
}
}
}
}
}
The problem is that my WPF application locks up and ceases to respond when it reaches this code.
To track down where, I put a MessageBox just before the writerStream line of the code to output what the reader was picking up.
It was certainly reading the log file just fine, but there appears to be a problem with writing it to the file.
As soon as it reaches the using (FileStream writerStream = new FileStream part of the code, it stops responding.
Is using the StreamWriter in this manner not valid, or have I just gone and dome something silly in the code?
Am also open to a better solution than what I'm trying to do here.
Simply what I understand is you need to copy a file from source to destination which may be deleted at any time.
I'll suggest you to use FileSystemWatcher to watch for source file changed event, then just simply copy the whole file from source to destination using File.Copy.
I've just solved the problem, and the issue was indeed something silly!
When creating the text file for the StreamWriter, I had forgotten to use .Dispose();. I had File.Create(filename); instead of File.Create(filename).Dispose(); This meant the text file was already open, and the StreamWriter was attempting to write to a file that was locked / in use.
The UI still locks up (as expected), as I've yet to implement this on a new thread as SteenT mentioned. However the program no longer crashes and the code correctly reads the log and outputs to a text file.
Also after a bit of refinement, my log reader/writer code now looks like this:
private void logCopier(string sourceFile, string destinationFile)
{
int num = 1;
string textLine = String.Empty;
long offset = 0L;
while (num == 1)
{
if (File.Exists(sourceFile))
{
FileStream stream = new FileStream(sourceFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
using (new StreamReader(stream))
{
stream.Seek(offset, SeekOrigin.Begin);
TextReader reader2 = new StreamReader(stream);
while ((textLine = reader2.ReadLine()) != null)
{
Thread.Sleep(1);
StreamWriter writer = new StreamWriter(destinationFile, true);
writer.WriteLine(textLine);
writer.Flush();
writer.Close();
offset = stream.Position;
}
continue;
}
}
else
{
num = 0;
}
}
}
Just putting this code up here in case anyone else is looking for something like this. :)
I was doing some trials on the basis of the following Q&A: Where does Console.WriteLine go in ASP.NET?.
The code I tried goes like below:
var fs = new System.IO.FileStream(#"D:\log.txt", System.IO.FileMode.Append);
var tr = new System.IO.StreamWriter(fs);
Console.SetOut(tr);
Console.WriteLine("My Default Debugging");
fs.Close();
Here I am setting the FileStream fs to StreamWriter tr and in turn setting it as Console.Out by calling Console.SetOut(). So, by that I am expecting it to write to the file by Console.WriteLine(). Though my file gets created, it is empty.
What can be the thing I am missing here?
try tr.WriteLine("string"); instead.
var fs = new System.IO.FileStream(#"D:\log.txt", System.IO.FileMode.Append);
var tr = new System.IO.StreamWriter(fs);
Console.SetOut(tr);
Console.WriteLine("My Default Debugging");
tr.Close();
fs.Close();
Maybe it's because you didn't close the StreamWriter before you closed the FileStream?
Becuase Console.WriteLine() doesn't do that?
Writes the specified data, followed by the current line terminator,
to the standard output stream.
1) I have created a program that has opened a twitter stream and writes everything to a file.
FileStream fs = new FileStream(#"\Database\twitterstream.txt", FileMode.Create);
TextWriter tmp = Console.Out;
StreamWriter sw = new StreamWriter(fs);
Console.SetOut(sw);
2) I have another program that I want to read said text file.
using (StreamReader sr = File.OpenText("C:\\Database\\twitterstream.txt"))
{
input = sr.ReadLine();
}
Because I want it to be in real time I am trying to have one program write, while at the same time the other program reads, however obviously it is throwing
"The process cannot access the file
'C:\Database\twitterstream.txt' because it is being used by another
process" back at me.
Is what I am trying to do possible? If so, how do I go about doing it?
Add a couple parameters to you FileStream constructor:
FileStream fs = new FileStream(
#"\Database\twitterstream.txt",
FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);
See FileStream on MSDN
for an application that uses a File as some sort of global storage for device reservations in a firm I need a way to read and write to a file (or lock a file, read from it, write to it, and unlock it). A little code snippet will shot what I mean:
FileStream in = new FileStream("storage.bin", FileMode.Open);
//read the file
in.Close();
//!!!!!
//here is the critical section since between reading and writing, there shouldnt
//be a way for another process to access and lock the file, but there is the chance
//because the in stream is closed
//!!!!!
FileStream out = new FileStream("storage.bin", FileMode.Create);
//write data to file
out.Close();
this should get something like this
LockFile("storage.bin");
//read from it...
//OVERwrite it....
UnlockFile("storage.bin");
the method should be absolute safe, since the program should run on 2000 devices at the same time
Simply holding a FileStream open with exclusive (not shared) access will prevent other processes from accessing the file. This is the default when opening a file for read/write access.
You can 'overwrite' a file that you currently hold open by truncating it.
So:
using (var file = File.Open("storage.bin", FileMode.Open))
{
// read from the file
file.SetLength(0); // truncate the file
// write to the file
}
the method should be absolute safe, since the program should run on 2000 devices at the same time
Depending on how often you're writing to the file, this could become a chokepoint. You probably want to test this to see how scalable it is.
In addition, if one of the processes tries to operate on the file at the same time as another one, an IOException will be thrown. There isn't really a way to 'wait' on a file, so you probably want to coordinate file access in a more orderly fashion.
You need a single stream, opened for both reading and writing.
FileStream fileStream = new FileStream(
#"c:\words.txt", FileMode.OpenOrCreate,
FileAccess.ReadWrite, FileShare.None);
Alternatively you can also try
static void Main(string[] args)
{
var text = File.ReadAllText(#"C:\words.txt");
File.WriteAllText(#"C:\words.txt", text + "DERP");
}
As per http://msdn.microsoft.com/en-us/library/system.io.fileshare(v=vs.71).aspx
FileStream s2 = new FileStream(name, FileMode.Open, FileAccess.Read, FileShare.None);
You need to pass in a FileShare enumeration value of None to open on the FileStream constructor overloads:
fs = new FileStream(#"C:\Users\Juan Luis\Desktop\corte.txt", FileMode.Open,
FileAccess.ReadWrite, FileShare.None);
I ended up writing this helper class to do this:
public static class FileHelper
{
public static void ReplaceFileContents(string fileName, Func<String, string> replacementFunction)
{
using (FileStream fileStream = new FileStream(
fileName, FileMode.OpenOrCreate,
FileAccess.ReadWrite, FileShare.None))
{
StreamReader streamReader = new StreamReader(fileStream);
string currentContents = streamReader.ReadToEnd();
var newContents = replacementFunction(currentContents);
fileStream.SetLength(0);
StreamWriter writer = new StreamWriter(fileStream);
writer.Write(newContents);
writer.Close();
}
}
}
which allows you to pass a function that will take the existing contents and generate new contents and ensure the file is not read or modified by anything else whilst this change is happening
You are likely looking for FileStream.Lock and FileStream.Unlock
I think you just need to use the FileShare.None flag in the overloaded Open method.
file = File.Open("storage.bin", FileMode.Open, FileShare.None);
My code in C# (asp.net MVC)
StreamWriter tw = new StreamWriter("C:\\mycode\\myapp\\logs\\log.txt");
// write a line of text to the file
tw.Write("test");
The file is created but is empty. No exception is thrown. I have never seen this before and I am stuck here; I just need to write some debugging output.
Please advise.
StreamWriter is buffered by default, meaning it won't output until it receives a Flush() or Close() call.
You can change that by setting the AutoFlush property, if you want to. Otherwise, just do:
StreamWriter tw = new StreamWriter("C:\\mycode\\myapp\\logs\\log.txt");
// write a line of text to the file
tw.Write("test");
tw.Close(); //or tw.Flush();
You need to either close or flush the StreamWriter after finishing writing.
tw.Close();
or
tw.Flush();
But the best practice is to wrap the output code in a using statement, since StreamWriter implements IDisposable:
using (StreamWriter tw = new StreamWriter("C:\\mycode\\myapp\\logs\\log.txt")){
// write a line of text to the file
tw.Write("test");
}
Neither flushed nor closed nor disposed.
try this
using (StreamWriter tw = new StreamWriter(#"C:\mycode\myapp\logs\log.txt"))
{
// write a line of text to the file
tw.Write("test");
tw.Flush();
}
or my preference
using (FileStream fs = new FileStream( #"C:\mycode\myapp\logs\log.txt"
, FileMode.OpenOrCreate
, FileAccess.ReadWrite) )
{
StreamWriter tw = new StreamWriter(fs);
tw.Write("test");
tw.Flush();
}
Use
System.IO.File.WriteAllText(#"path\te.txt", "text");
FileStream fs = new FileStream("d:\\demo.txt", FileMode.CreateNew,
FileAccess.Write);
StreamWriter sw = new StreamWriter(fs, System.Text.Encoding.ASCII);
int data;
sw.Write("HelloWorld");
sw.Close();
fs.Close();
The problem is when StreamWriter Object is created with reference of FileStream Object , SW object will be always expecting some data till SW object is Closed.
So After using sw.Close();
Your Opened File will get closed and get ready for showing Output.
Ya in VB.net this was not needed but it seems with CSharp you need a Writer.Flush call to force the write. Of course Writer.Close() would force the flush as well.
We can also set the AutoFlush Property of the StreamWriter instance:
sw.AutoFlush = true;
// Gets or sets a value indicating whether the StreamWriter
// will flush its buffer to the underlying stream after every
// call to StreamWriter.Write.
From: http://msdn.microsoft.com/en-us/library/system.io.streamwriter.autoflush(v=vs.110).aspx
an alternative
FileStream mystream = new FileStream("C:\\mycode\\myapp\\logs\\log.txt",
FileMode.OpenOrCreate, FileAccess.Write);
StreamWriter tw = new StreamWriter(mystream);
tw.WriteLine("test");
tw.close();
Try to close the file or add \n to the line such as
tw.WriteLine("test");
tw.Close();