Writing to file best practises (locked files/overwriting) - c#

If I am working with files in C#, what is the best way to check if a file is locked in C#?
If I use File.OpenWrite(), which returns a FileStream, and this returns CanWrite = false, is this a way of checking so?
Also, what is it wise to write to just one location in my code? So I specify a path to write to like "TestExample.txt", but then if I run my code, successfully write to the file, run again, the same data will be in there. Is it possible to overwrite the data already in a file altogether? Or do I need to manually delete (I know this sounds naive).
Thanks

File.OpenWrite will throw an IOException if the file is locked, so calling that method and then checking the CanWrite property would not be a good approach. You will need a try-catch handling the IOException.
If you want to replace the contents of your file, you can simply delete it before writing to it (if it exists):
try
{
if (File.Exists(fileName))
{
File.Delete(fileName);
}
using (FileStream stream = File.OpenWrite(fileName))
using (StreamWriter writer = new StreamWriter(stream))
{
writer.Write("your content");
}
}
catch (IOException)
{
// the file is locked
}

Related

c# check if file is open

I need to verify if specific file is open to prevent the copy of that file.
I try lot of examples but any doesn't work! I try, for example, this:
protected virtual bool IsFileLocked(FileInfo file)
{
FileStream stream = null;
try
{
stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None);
}
catch (IOException)
{
//the file is unavailable because it is:
//still being written to
//or being processed by another thread
//or does not exist (has already been processed)
return true;
}
finally
{
if (stream != null)
stream.Close();
}
//file is not locked
return false;
}
I need orientation... where am I fail? suggestions?
If you want to know whether your application already had the file open, you should just save the FileStream in a field, and reset the field to null when you close the stream. Then you can simply test and get the FileStream of the file.
If you want to know whether another application already has the file open, then there is not much you can do. You'll might get an exception when you try to open the file. But even if you knew, then you wouldn't be able to prevent the copy of that file, because you don't have a reference to the file or its FileStream in your application.
You can suffer from a thread race condition on this which there are documented examples of this being used as a security vulnerability. If you check that the file is available, but then try and use it you could throw at that point, which a malicious user could use to force and exploit in your code.
Your best bet is a try catch / finally which tries to get the file handle.
try
{
using (Stream stream = new FileStream("MyFilename.txt", FileMode.Open))
{
// File/Stream manipulating code here
}
} catch {
//check here why it failed and ask user to retry if the file is in use.
}
or
see this another options
https://stackoverflow.com/a/11060322/2218635

File.Open doesn't throw IOException when File.Move does

I face weird problem with IOException on different servers. Here is my story:
I have win server (C#) that monitors folder for file changes. Also, a FTP server (WinSSHD) is pointed on same folder. When someone uploads a file WinService checks is write complete or not. If file is uploaded WinService renames it via File.Move method.
Is write complete check is made by File.Open method. Like this:
public static bool IsWriteComplete(string filePath)
{
bool isWriteComplete;
FileStream stream = null;
try
{
stream = File.Open(filePath, FileMode.Open, FileAccess.Write, FileShare.ReadWrite|FileShare.Delete);
isWriteComplete = true;
}
catch (IOException)
{
isWriteComplete = false;
}
catch (Exception ex)
{
isWriteComplete = false;
}
finally
{
if (stream != null) { stream.Close(); }
}
return isWriteComplete;
}
For some reason on one server it works perfectly (Win2003SP2) and on another one (Win2003SP1) is not working at all. The IsWriteComplete method says True, WinServer tries to move file and dies by IOException later. I haven't found any references regarding such issue.
To fix the issue I replaced File.Open by File.Move.
Before:
stream = File.Open(filePath, FileMode.Open, FileAccess.Write, FileShare.ReadWrite|FileShare.Delete);
After:
File.Move(filePath, filePath);
And now it works on second server (Win2003SP1) and doesn't work on first one (Win2003SP2).
Does anybody know why it works as such?
When you use File.Open you have a "race condition", even if you use FileShare.None - after you close the file, another thread/process can sneak in and lock the file (open it) before you call File.Move. This other process might not be the FTP server, but could be something you are not even aware of, such as a virus checker. Thus you should use File.Move instead of File.Open, and catch the IOException if the File.Move fails, and then retry, until it succeeds.
When you use FileShare.ReadWrite|FileShare.Delete, you allow other processes to read, write or delete the file while you're opening it. On the other side, you can open the file while others also access it. So, try FileShare.None to open the file exclusively, which should fail as long as the file is in use by the FTP server.
Also, you should use FileAccess.ReadWrite to make sure that you have full access to the file. You do not know how the FTP server locks the file, maybe it allows other processes to open the file in read-mode and declines write mode while the upload is still in process. So, FileAccess.ReadWrite is better.
MSDN reference: http://msdn.microsoft.com/en-us/library/system.io.fileshare.aspx and http://msdn.microsoft.com/en-us/library/system.io.fileaccess.aspx
About your code:
catch (IOException)
{
isWriteComplete = false;
}
catch (Exception ex)
{
isWriteComplete = false;
}
The catch block for IOException is not neccessary if you also catch Exception...
Alternatively, you can check in other way then open method.
FileInfo fileInfo = new FileInfo(filePath);
bool isNormal = ((fileInfo.Attributes & FileAttributes.Normal) == FileAttributes.Normal);
//or
bool isReadOnly = ((fileInfo.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly);
You can find the method in either way in order to understand whether file is available or not. And you can continue based upon the status.
Please let me know if you are looking for some other things.
Found the root cause of the behavior.
There was different FTP service installed: Techia. For some reason Tectia doesn't set write lock on uploading files. That's why File.Open(filePath, FileAccess.Write) doesn't throw IOException.

overwriting file with File.CreateText (C#)

I am experiencing the following problem. I am using .NET Framework 1.1 and I am trying to overwrite a file using this code:
try
{
using (StringWriter writer = new StringWriter())
{
Server.Execute(path, writer);
using (StreamWriter sr = File.CreateText(filepath + fileName))
{
sr.WriteLine(writer.ToString());
}
}
}
catch (Exception exc)
{
...
}
Sometimes it works fine, but sometimes it does not overwrite the file and no exception is thrown. Could someone tell me what the issue may be or how to handle why it doesn't overwrite the file?
Why not just:
File.WriteAllText(Path.Combine(filepath, fileName), writer.ToString())
From MSDN:
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.
Could someone tell me what the issue may be or how to handle why it
doesn't overwrite the file?
Well, to answer your actual question, File.CreateText(string file) is behaving exactly as intended. if filepath + fileName to use your example, is a file that already exists, it opens the file instead of creating it. (It does not overwrite).
You could first check to see if the file exists using File.Exists(string file) then File.Delete(string file).
If File.CreateText(string file) doesn't suit your needs, you could try a different type. Maybe FileInfo?
Microsoft Says:
Creates or opens a file for writing UTF-8 encoded text.
Source: https://msdn.microsoft.com/en-us/library/system.io.file.createtext%28v=vs.110%29.aspx
over write can also be achieved with built in file.copy method.
File.copy has overload -
File.Copy Method (Source, Destination, OverWrite)
more info on msdn
hope this helps.

File.Copy method makes file inaccessible

I am struggling with this for some time now. I can not access a file after I call File.Copy method. Here is what I tried:
File.Copy(sourceFile, destinationFile, true);
FileStream fs = File.Open(destinationFile, FileMode.Open);
I am getting UnauthorizedAccessException on the second line. It says: Access to the path ... is denied. I have also tried suggestion stated here but that didn't work.
Any help is appreciated.
EDIT: Here is what I found out. If I do this:
File.Copy(sourceFile, destinationFile, true);
FileStream fs = File.Open(destinationFile, FileMode.Open, FileAccess.Read);
It doesn't throw exception. The file I am trying to access is read only. So, I tried to remove read only attribute like this:
File.Copy(sourceFile, destinationFile, true);
FileInfo fileInfo = new FileInfo(destinationFile);
fileInfo.IsReadOnly = false;
FileStream fs = File.Open(destinationFile, FileMode.Open, FileAccess.ReadWrite);
And I get the same exception as before. By the way, I checked if I can open file manually and edit it, and I can. Of course, when I uncheck read only check box. I have also checked file attributes in windows explorer while debugging, right after the third line, and the file is no longer read only. Having all that in checked, I don't understand why is the exception being thrown on the fourth line.
Are you sure it's ONLY files copied using File.Copy that you can't open, and not every file in the target folder? And is this a regular NTFS folder, or network share?
If you are running an antivirus or security software, try disabling it. After a file is created they will often open a file to scan it.
Update
According to http://msdn.microsoft.com/en-us/library/b9skfh7s.aspx - UnauthorizedAccessException thrown by File.Open will not give the message 'Access to the path... is denied'. (edit: I can't see that message for File.Copy either, so this might be wrong)
I suspect it is your File.Copy that fails with that exception, and you don't have rights to read the source file, or write the target file. You're probably looking at the highlighted source code line, which shows the next line to be exectued.
So - maybe your copy fails, not the File.Open ?
Try this!
private bool CheckFileHasCopied(string FilePath)
{
try
{
if (File.Exists(FilePath))
{
using (File.OpenRead(FilePath))
{
return true;
}
}
else
{
return false;
}
}
catch (Exception)
{
Thread.Sleep(2000);
return CheckFileHasCopied(FilePath);
}
}
if (CheckFileHasCopied(destinationFile)) { File.Delete(sourceFile); }

How to delete a file dynamically in c#?

while deleting a file dynamically using c# it couldn't be deleted because its being used
by another process but i have no other process which has been using this file.
foreach (string file in filess)
{
// FileInfo fi2 = new FileInfo(file);
// fi2.Delete();
File.Delete(file);
// ii = 0;
}
Generally if it say that it is used by another process then you should consider this as true. To have sure you can verify this with this tool: Process Explorer
It will tell you what process is locking file.
You should always make sure you close the streams you opened it:
using (FileStream stream = File.Create("C:\\1.txt"))
{
// your code goes here
}// the object will be closed here
because if you don't put this using block it will cause a lot of bugs even if you closed it manually with stream.Close();
If the File is in use you can't delete it, do the deletion in a try catch clauses. I would determine if the process using that file is your own app or some other process. You can use the Unlocker for that.
This is How you can delete simply
// File.Copy(#"‪C:\Users\Asus\Desktop\New.txt", #"D:\New.txt");
string rootFolder = #"D:\";
string authorsFile = "Gym.mdf";
File.Delete(Path.Combine(rootFolder, authorsFile));
string authorsFile2 = "Gym_log.ldf";
File.Delete(Path.Combine(rootFolder, authorsFile2));

Categories

Resources