I'm monitoring a folder for new files, and when the new file is present I read (and save in a txt) the file as following:
FileStream file = File.Open(this.filePath, FileMode.Open, FileAccess.Read);
StreamReader reader = new System.IO.StreamReader(file);
string text = reader.ReadToEnd();
reader.Close();
If I copy/paste in the folder the source file, I receive an IOExcpetion that tells me that the file is used by another process.
If I cut/paste in the folder, all works.
Moreover locking problem happens also If I copy (but also cut in this case)/paste the file from another machine into the monitored folder.
Do you have an idea about what is happening?
There is a safer way to access to the file in order to avoid this type of locks?
Thanks!
Here is a little snippet I do to ensure the file is finished copying or not in use by another process.
private bool FileUploadCompleted(string filename)
{
try
{
using (FileStream inputStream = File.Open(filename, FileMode.Open,
FileAccess.Read,
FileShare.None))
{
return true;
}
}
catch (IOException)
{
return false;
}
}
Then you can implement this before your process logic
while (!FileUploadCompleted(filePath))
{
//if the file is in use it will enter here
//So you could sleep the thread here for a second or something to allow it some time
// Also you could add a retry count and if it goes past the allotted retries you
// can break the loop and send an email or log the file for manual processing or
// something like that
}
Related
My objective is to write some data into an excel.
Here i am opening a file with file stream by exclusive lock (FileMode.Open, FileShare.Read etc., I need to lock the file to restrict others writing into excel while i am processing.) then writing some content into it and finally close the stream, so that other threads can write into this file. I am using EPPlus(5.7.4) version.
The code i am using here is :
public void WriteToExcel()
{
using (var stream = new FileStream(path, FileMode.Open, FileAccess.ReadWrite, FileShare.Read))
using (var excelPackage = new ExcelPackage(stream))
{
DoSomething(excelPackage);
excelPackage.SaveAs(stream);
stream.Close();
}
}
public void DoSomething(ExcelPackage excelPackage)
{
var cell = excelPackage.Workbook.Worksheets[0].Cells[2, 3];
cell.Value = "some value";
}
I put a break point in using statement and opened excel in the middle of execution and it showing a message saying like below which is correct.
But once i finish with execution when i try to open excel file it showing below error message.
We found a problem with some content in Sample.xlsx. Do you want us to try to recover as much as we can? if you trust the source of this book, Click Yes
I tried in different ways but none worked for me, as same error message is displaying. Can someone help me resolving this issue.
The problem is that you're reading from and rewriting to the same file stream simultaneously.
You can test this by changing excelPackage.SaveAs(new FileInfo("Book2.xlsx")); and create a new file - your file will be created without any issues.
You could open your original document, write the changes to a new file, then delete the original file and rename the new file back to the original name:
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
using (var stream = new FileStream("Book1.xlsx", FileMode.Open, FileAccess.ReadWrite, FileShare.Read))
using (var excelPackage = new ExcelPackage(stream))
{
DoSomething(excelPackage);
excelPackage.SaveAs(new FileInfo("Book2.xlsx"));
}
File.Delete("Book1.xlsx");
File.Move("Book2.xlsx", "Book1.xlsx");
The caveat with this is that if you have multiple things trying to access that file, then they might throw FileNotFound exceptions if they happen to try to open Book1.xlsx after it's delete and before Book2.xlsx is renamed.
That said, if you're dealing with that level of parallelism then you shouldn't be using a Excel file.
Side note: You don't need stream.Close(); as the using block automatically closes the stream.
Below code useful to me, you can refer it.
public void WriteToExcel()
{
string path = #"C:\Use**op\aa.xlsx";
FileInfo file = new FileInfo(path);
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
using (ExcelPackage package = new ExcelPackage(file))
{
DoSomething(package);
}
}
public void DoSomething(ExcelPackage package)
{
ExcelWorksheet worksheet = package.Workbook.Worksheets[0];
worksheet.Cells[2,4].Value = "some value";
package.Save();
}
When I open an excel file, a hidden temporary file is generated in the same folder. I can open it with the TotalCommander Viewer, but I always get an IO exception when trying to open with powershell or c#.
new FileStream(#"D:\~$test.xlsx", FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
System.IO.IOException: 'The process cannot access the file 'D:~$test.xlsx' because it is being used by another process.'
So how can I get the content?
Unfortunately for some reason you can not open the direct file, so I suggest another method when you copy a the file to a temp file, then read it and finally you delete the temp file, this way you can read it, I suppose TotalCommander uses the same method for opening files in Viewer.
static void Main(string[] args)
{
CopyReadAndDelete(#"c:\Documents\~$test.xlsx");
}
static void CopyReadAndDelete(string filePath)
{
var tempFileFullPath = Path.Combine(Path.GetDirectoryName(filePath), Guid.NewGuid().ToString());
File.Copy(filePath, tempFileFullPath);
try
{
using (var sr = new StreamReader(tempFileFullPath))
{
Console.WriteLine(sr.ReadToEnd()); //or do anything with the content
}
}
finally
{
File.Delete(tempFileFullPath);
}
}
Using c#, is there a way to check that a file is in use. More specifically, I need a way to monitor a directory of .wav files and see which sound file has been loaded.
Note. It can be loaded by different applications.
I've had a look at Core Audio.. but I cannot seem to find an answer there.
I've also tried to code that if the file is locked but that also doesnt provide a solution. So if you know of a way to determine which sound file (.wav) is currently being played, please comment.
protected virtual bool IsFileLocked(FileInfo file)
{
FileStream stream = null;
try
{
stream = file.Open(FileMode.Open, FileAccess.Read, 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;
}
Here is the reference link : File is in Use
Hope it helps.
How do I open (using c#) a file that is already open (in MS Word, for instance)? I thought if I open the file for read access e.g.
FileStream f= new FileStream('filename', FileMode.Open, FileAccess.ReadWrite);
I should succeed, but I get an exception:
"the process cannot access the file
because it is locked ..."
I know there must be a way to read the file irrespective of any locks placed on it, because I can use windows explorer to copy the file or open it using another program like Notepad, even while it is open in WORD.
However, it seems none of the File IO classes in C# allows me to do this. Why?
You want to set FileAccess=Read and FileShare=ReadWrite. Here is a great article on this (along with an explanation of why):
http://coding.infoconex.com/post/2009/04/How-do-I-open-a-file-that-is-in-use-in-C.aspx
Your code is using the FileAccess.Read*Write* flag. Try just Read.
I know this is an old post. But I needed this and I think this answer can help others.
Copying a locked file the way the explorer does it.
Try using this extension method to get a copy of the locked file.
Usage example
private static void Main(string[] args)
{
try
{
// Locked File
var lockedFile = #"C:\Users\username\Documents\test.ext";
// Lets copy this locked file and read the contents
var unlockedCopy = new
FileInfo(lockedFile).CopyLocked(#"C:\Users\username\Documents\test-copy.ext");
// Open file with default app to show we can read the info.
Process.Start(unlockedCopy);
}
catch (Exception ex)
{
Trace.TraceError(ex.Message);
}
}
Extension method
internal static class LockedFiles
{
/// <summary>
/// Makes a copy of a file that was locked for usage in an other host application.
/// </summary>
/// <returns> String with path to the file. </returns>
public static string CopyLocked(this FileInfo sourceFile, string copyTartget = null)
{
if (sourceFile is null)
throw new ArgumentNullException(nameof(sourceFile));
if (!sourceFile.Exists)
throw new InvalidOperationException($"Parameter {nameof(sourceFile)}: File should already exist!");
if (string.IsNullOrWhiteSpace(copyTartget))
copyTartget = Path.GetTempFileName();
using (var inputFile = new FileStream(sourceFile.FullName, FileMode.Open,
FileAccess.Read, FileShare.ReadWrite))
using (var outputFile = new FileStream(copyTartget, FileMode.Create))
inputFile.CopyTo(outputFile, 0x10000);
return copyTartget;
}
}
I want to take a file that stored already in the isolated storage, and copy it out, somewhere on the disk.
IsolatedStorageFile.CopyFile("storedFile.txt","c:\temp")
That doesn't work. Throws IsolatedStorageException and says "Operation not permitted"
I don't see anything in the docs, other than this, which just says that "Some operations aren't permitted", but doesn't say what, exactly. My guess is that it doesn't want you copying out of isolated storage to arbitrary locations on disk. The docs do state that the destination can't be a directory, but even if you fix that, you still get the same error.
As a workaround, you can open the file, read its contents, and write them to another file like so.
using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForAssembly())
{
//write sample file
using (Stream fs = new IsolatedStorageFileStream("test.txt", FileMode.Create, store))
{
StreamWriter w = new StreamWriter(fs);
w.WriteLine("test");
w.Flush();
}
//the following line will crash...
//store.CopyFile("test.txt", #"c:\test2.txt");
//open the file backup, read its contents, write them back out to
//your new file.
using (IsolatedStorageFileStream ifs = store.OpenFile("test.txt", FileMode.Open))
{
StreamReader reader = new StreamReader(ifs);
string contents = reader.ReadToEnd();
using (StreamWriter sw = new StreamWriter("nonisostorage.txt"))
{
sw.Write(contents);
}
}
}