So, I'm trying to create a login form, but I need to read and write to files etc, first of all; I'm creating a file then writing 'test' to the file, but if I then delete the file and try and issue my commands at the same time:
FileIO.FileCheck("Usernames.pheonix");
FileIO.WriteFile("Usernames.pheonix", "test");
It pulls me an error;
The process cannot access the file 'C:\Users\XXX\Desktop\Pheonix Launcher\Pheonix\bin\Debug\Usernames.pheonix' because it is being used by another process.
I can't seem to get me head around why it keeps on doing this, here are my Read/Write file:
public static void createFile(String FileName)
{
File.Create(FileName);
}
public static void WriteFile(String File ,String Message)
{
FileStream fs1 = new FileStream(File, FileMode.OpenOrCreate, FileAccess.Write);
StreamWriter writer = new StreamWriter(fs1);
writer.Write(Message);
writer.Close();
}
public static void FileCheck(String fileName)
{
if (File.Exists(fileName))
Console.WriteLine("File exists.");
else
createFile(fileName);
}
File.Create does create a file - and return an open stream to it. Put it in a using block. (Don't just call close on it - that would be a bug because it is not exception safe).
Actually, looking closer I see that you don't need this at all due to FileMode.OpenOrCreate. The file will be created anyway.
Related
I have seen several post for this problem .I have implemented all suggestion like using flush() , close() method on streamwriter and connection Object,use GC.Collect() to force cleanup,, use using{} to autodispose
I am Doing Simple Get Operation from DB and write to text file ..here is my Code
public void WriteToFile(string ProductName)
{
//Already Got Data from DB and stored in "ProductName"
//saving in File
if (!File.Exists(path11))
{
File.Create(path11);
StreamWriter tw = new StreamWriter(path11);
tw.WriteLine(ProductName+"#"+DateTime.Now.ToString());
tw.Flush();
tw.Close();
}
else if (File.Exists(path11))
{
StreamWriter tw = new StreamWriter(path11, true);
tw.WriteLine(ProductName + "#" + DateTime.Now.ToString());
tw.Flush();
tw.Close();
}
GC.Collect();
}
Another suggestion I Got is to lock the object ..But I cannot implement it ..
Any suggestion would be Helpful
File.Create creates the file and returns an open stream. You don't really need all that logic. Just use new StreamWriter(path11, true) which will create the file if it doesn't exist and append to it if it does. Also using is helpful:
public void WriteToFile(string ProductName)
{
//Get Data from DB and stored in "ProductName"
using (var tw = new StreamWriter(path11, true))
{
tw.WriteLine(ProductName+"#"+DateTime.Now.ToString());
}
}
FileCreate returns a stream which you should use to instantiate StreamWriter:
var file = File.Create(path11);
StreamWriter tw = new StreamWriter(file);
And you should use using blocks to make sure your stream and file is closed when you're finished writing.
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. :)
When I create my log.txt with File.Create(Path.Combine(PATH, NAME)); and then try to read from it I get an exception: {System.IO.IOException: The process cannot access the file 'c:\temp\log.txt' because it is being used by another process..
If the log.txt file exits and not created in the method I can read and write to the log wihtout any problems.
Is the log.txt created async and the problem is that the program is trying to read it before it's created?
public static void WriteToLog(string text)
{
try
{
if (!Directory.Exists(PATH))
{
Directory.CreateDirectory(PATH);
}
if( !File.Exists(Path.Combine(PATH, NAME)) )
{
File.Create(Path.Combine(PATH, NAME));
}
var logLines = File.ReadAllLines(Path.Combine(PATH, NAME)).ToList<string>();
logLines.Insert(0, "-------------------------------------------------End New Log");
logLines.Insert(0, text);
logLines.Insert(0, "-------------------------------------------------Start New Log");
File.WriteAllLines(Path.Combine(PATH, NAME), logLines);
}
catch (Exception ex)
{
}
}
File.Create creates a filestream, which is open after the creation. so the file is used by its own process.
just change it to
using(var f = File.Create(Path.Combine(PATH, NAME))) { } ;
File.Create has a return value of type FileStream. That FileStream should be Closed (or Disposed) if you do not intend to use it for anything.
For a log file, however, I'd usually create the FileStream directly by constructing a FileStream object, using one of the constructors that accepts a FileShare parameter. That way, you can keep the stream open, but indicate that other programs should be able to open it for reading:
var fs = new FileStream(Path.Combine(PATH, NAME),
FileMode.OpenOrCreate,
FileAccess.Write,
FileShare.Read); //Now other people can access the log file whilst I'm still writing to it
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);
Does anyone know of a way to (reasonably simple) create a file without actually opening/locking it? In File class, the methods for file creation always return a FileStream. What I want to do is to create a file, rename it (with File.Move) and then use it.
Now I have to:
Create it
Close
Rename
Reopen for use
Maybe you can try using File.WriteAllText Method (String, String)
with the file name and an empty string.
Creates a new file, writes the
specified string to the file, and then
closes the file. If the target file
already exists, it is overwritten.
using (File.Create(...)) { }
While this will briefly open your file (but close it again right away), the code should look quite unobtrusive.
Even if you did some P/Invoke call to a Win32 API function, you would get a file handle. I don't think there's a way to silently create a file without having it open right afterwards.
I think the real issue here is why you go about creating your file in the way you've planned. Creating a file in one place simply to move it to another location doesn't seem very efficient. Is there a particular reason for it?
What about using File.WriteAllBytes method?
// Summary:
// Creates a new file, writes the specified byte array to the file, and then
// closes the file. If the target file already exists, it is overwritten.
Another way is to use FileStream and Close it after creating the file. It will not lock the file. The code will look like:
FileStream fs = new FileStream(filePath, FileMode.Create);
fs.Flush(true);
fs.Close();
You just after this you can rename it as well or move it some other location.
Below is the Test program to test functionality.
using System;
using System.Collections.Generic;
using System.IO; using
System.Linq;
using System.Text;
namespace FileLocking {
class Program
{
static void Main(string[] args)
{
string str = #"C:\Test\TestFileLocking.Processing";
FileIOTest obj = new FileIOTest();
obj.CreateFile(str);
}
}
class FileIOTest
{
internal void CreateFile(string filePath)
{
try
{
//File.Create(filePath);
FileStream fs = new FileStream(filePath, FileMode.Create);
fs.Flush(true);
fs.Close();
TryToAccessFile(filePath);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
void TryToAccessFile(string filePath)
{
try
{
string newFile = Path.ChangeExtension(filePath, ".locked");
File.Move(filePath, newFile);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
} }
If you use File.Create(commented in above code) then it will give error saying file is being used by another process.
Incredibly grotty hack, probably the most complicated way to achieve your goal:
use Process class
processInfo = new ProcessStartInfo("cmd.exe", "/C " + Command);
processInfo.CreateNoWindow = true;
processInfo.UseShellExecute = false;
process = process.Start(processInfo);
process.WaitForExit();
where Command would be echo 2>> yourfile.txt