I have a certain requirement. When current line of code throwing exception, I want to move to next line
FileStream fs = new FileStream("D:/temp/product.xml", FileMode.Open, FileAccess.Read);
sometimes D:/ drive don't have xml file, it throwing FileNotFoundException and jumping control out of scope. but then in next line I want to check another location
FileStream fs = new FileStream("//letp.rf.servername.com/products/product.xml", FileMode.Open, FileAccess.Read);
How can I fix this issue?
Use defensive check and check whether the file exists first using File.Exists(String) method before actually accessing it. Again, wherever possible we should use Defensive Check rather Exception Handling since exception handling is expensive operation. How expensive are exceptions in C#?
Finally, you can wrap this entirely in a try .. catch block to make sure catching any other exception down the line and logging them.
try
{
if (File.Exists("D:/temp/product.xml"))
{
FileStream fs = new FileStream("D:/temp/product.xml", FileMode.Open, FileAccess.Read);
}
else
{
// check another location
}
}
catch (Exception ex)
{
// perform logging
}
All you need to do is wrap your code in a try-catch block, for example:
FileStream fs = null;
try
{
fs = new FileStream("D:/temp/product.xml", FileMode.Open, FileAccess.Read);
}
catch (FileNotFoundException e)
{
// Retry another file,
}
If the retry can also fail, you'll have to wrap it also.
(Btw, Rahul's answer is better and easier)
To use this in a loop:
FileSystem fs = null;
foreach (var file in files) // files contains the file paths
{
// Solution #1
try
{
fs = new FileStream(file, FileMode.Open, FileAccess.Read);
break;
}
catch (FileNotFoundException e) { }
// Or you can use File.Exists as per Rahul's answer
// Solution #2
if (File.Exists(file))
{
fs = new FileStream(file, FileMode.Open, FileAccess.Read);
break;
}
}
Don't use exceptions to check whether a file exists, but check whether the file exists via File.Exists:
string defaultPath = "D:/temp/product.xml";
string alternativePath = "//letp.rf.servername.com/products/product.xml";
string path = File.Exists(defaultPath) ? defaultPath : alternativePath;
FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read);
If you want to check for another path if the second one is not found, you might want to use the following approach with an array of paths. With that, you are totally flexible how many paths you want to check.
string[] paths = new string[] { #"C:\first\path\product.xml", #"C:\second\path\product.xml", #"C:\third\path\product.xml"};
string path = paths.FirstOrDefault(p => File.Exists(p));
if(path == null)
{
Console.WriteLine("None of the files exists!");
}
else
{
FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read);
}
Just use try and catch and loop:
foreach (var file in files)
{
try
{
FileStream fs = new FileStream(file , FileMode.Open, FileAccess.Read);
}
catch(Exception ex)
{}
}
Related
I need to append data to a file, but if the file does not exist I need to add a header before appending.
If I open the file with FileMode.Append, I cannot see a way to work out if the file is new or not.
If I open the file with
FileStream file;
boolean isNew;
try
{
file = File.Open(path, FileMode.CreateNew);
isNew = true;
}
catch (IOException ex)
{
file = File.Open(path, FileMode.Append);
isNew = false;
}
I run into the risk of another process deleting the file between the the 2 open calls and not detecting the creation of the new file.
What is the recommended way of opening for appending and detecing if create or append?
Does this do what you need?
try
{
var file = File.Open(path, FileMode.OpenOrCreate, FileAccess.ReadWrite);
if (file.Length == 0)
{
// do header stuff
}
// do the rest
}
catch (IOException ex)
{
// handle io ex.
}
Try something like this:
if (!File.Exists(path))
{
file = File.Open(path, FileMode.CreateNew);
isNew = true;
return;
}
// otherwise append to existing file
file = File.Open(path, FileMode.Append);
isNew = false;
I'm running into an error that I can't catch and it should not be there.
if (System.IO.File.Exists (PathToMyFile))
{
try{
FileStream fs = new FileStream(PathToMyFile, FileMode.Open, FileAccess.Read);
BinaryReader br = new BinaryReader(fs);
Byte[] bytes = br.ReadBytes((Int32)fs.Length);
br.Close();
fs.Close();
myFile =Convert.ToBase64String (bytes) ;
}
catch{}
}
For some reason , sometimes I get a exception error that the file does not exist when It most definitely is there. The very first "If statement" even says it is there yet when trying to open the file I sometimes get a massive app crash that the catch does not "catch" .
Like I said, it's a random error, most of the time the code is perfect but the odd occasion seems to throw an error that the app stops working .
First thing is to make sure you close the file\stream
So you can call fs.Close() or using
if (File.Exists(pathToMyFile))
{
try
{
using (var fs = new FileStream(pathToMyFile, FileMode.Open, FileAccess.Read))
{
BinaryReader br = new BinaryReader(fs);
Byte[] bytes = br.ReadBytes((Int32) fs.Length);
br.Close();
fs.Close();
myFile = Convert.ToBase64String(bytes);
}
}
catch
{
// Log exception
}
}
Second, if you need to read the file as string, simply use
if (File.Exists(pathToMyFile))
{
try
{
myFile = File.ReadAllText(pathToMyFile);
}
catch
{
// Log exception
}
}
I have a C# app that tries to read a log file which is being written to by another app. When I try to read the file, I get IOException
"The process cannot access the file ... because it is being used by
another process."
What I tried using so far are the following, but none of them fix the problem
var log = File.ReadAllText(logPath);
var stream = new FileStream(logPath, FileMode.Open);
using (var stream = File.Open(logPath, FileMode.Open))
{
}
try this:
FileStream logFileStream = new FileStream("c:\test.txt", FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
StreamReader logFileReader = new StreamReader(logFileStream);
while (!logFileReader.EndOfStream)
{
string line = logFileReader.ReadLine();
// Your code here
}
// Clean up
logFileReader.Close();
logFileStream.Close();
edited with MethodMan's suggestions
using(FileStream logFileStream = new FileStream(#"c:\test.txt", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
using(StreamReader logFileReader = new StreamReader(logFileStream))
{
string text = logFileReader.ReadToEnd();
// Your code..
}
}
You can do nothing, if the "another app" does not use Share.Read while creating/opening the file.
I'm working with a file stream in C#. It's a storage cache, so if something goes bad writing the file (corrupted data, ...), I need to delete the file and rethrow the exception to report the problem. I'm thinking on how to implement it in the best way. My first attempt was:
Stream fileStream = null;
try
{
fileStream = new FileStream(GetStorageFile(),
FileMode.Create, FileAccess.Write, FileShare.Write);
//write the file ...
}
catch (Exception ex)
{
//Close the stream first
if (fileStream != null)
{
fileStream.Close();
}
//Delete the file
File.Delete(GetStorageFile());
//Re-throw exception
throw;
}
finally
{
//Close stream for the normal case
if (fileStream != null)
{
fileStream.Close();
}
}
As you will see, if something goes bad writing the file, the fileStream will be closed twice. I know that it works, but I don't think that is the best implementation.
I think that I could remove the finally block, and close the stream in the try block, but I have posted this here because you guys are experts and I want to hear the voice of an expert.
If you put the fileStream in a using block you don't need to worry about closing it, and then just leave the cleaning up (deleting of the file in the catch block.
try
{
using (FileStream fileStream = new FileStream(GetStorageFile(),
FileMode.Create, FileAccess.Write, FileShare.Write))
{
//write the file ...
}
}
catch (Exception ex)
{
File.Delete(GetStorageFile());
//Re-throw exception
throw;
}
I believe what you want is this:
var fs = new FileStream(result.FilePath, FileMode.Open, FileAccess.Read, FileShare.None, 4096, FileOptions.DeleteOnClose);
I've used it with ASP.Net to have the web server return a result to a temp file that's on disk, but to make sure it's cleaned up after the web server finishes serving it to the client.
public static IActionResult TempFile(string tempPath, string mimeType, string fileDownloadName)
{
var fs = new FileStream(tempPath, FileMode.Open, FileAccess.Read, FileShare.None, 4096, FileOptions.DeleteOnClose);
var actionResult = new FileStreamResult(fileStream: fs, contentType: mimeType)
{
FileDownloadName = fileDownloadName
};
return actionResult;
}
I have a windows service writes its log in a text file in a simple format.
Now, I'm going to create a small application to read the service's log and shows both the existing log and the added one as live view.
The problem is that the service locks the text file for adding the new lines and at the same time the viewer application locks the file for reading.
The Service Code:
void WriteInLog(string logFilePath, data)
{
File.AppendAllText(logFilePath,
string.Format("{0} : {1}\r\n", DateTime.Now, data));
}
The viewer Code:
int index = 0;
private void Form1_Load(object sender, EventArgs e)
{
try
{
using (StreamReader sr = new StreamReader(logFilePath))
{
while (sr.Peek() >= 0) // reading the old data
{
AddLineToGrid(sr.ReadLine());
index++;
}
sr.Close();
}
timer1.Start();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void timer1_Tick(object sender, EventArgs e)
{
using (StreamReader sr = new StreamReader(logFilePath))
{
// skipping the old data, it has read in the Form1_Load event handler
for (int i = 0; i < index ; i++)
sr.ReadLine();
while (sr.Peek() >= 0) // reading the live data if exists
{
string str = sr.ReadLine();
if (str != null)
{
AddLineToGrid(str);
index++;
}
}
sr.Close();
}
}
Is there any problem in my code in reading and writing way?
How to solve the problem?
You need to make sure that both the service and the reader open the log file non-exclusively. Try this:
For the service - the writer in your example - use a FileStream instance created as follows:
var outStream = new FileStream(logfileName, FileMode.Open,
FileAccess.Write, FileShare.ReadWrite);
For the reader use the same but change the file access:
var inStream = new FileStream(logfileName, FileMode.Open,
FileAccess.Read, FileShare.ReadWrite);
Also, since FileStream implements IDisposable make sure that in both cases you consider using a using statement, for example for the writer:
using(var outStream = ...)
{
// using outStream here
...
}
Good luck!
Explicit set up the sharing mode while reading the text file.
using (FileStream fs = new FileStream(logFilePath,
FileMode.Open,
FileAccess.Read,
FileShare.ReadWrite))
{
using (StreamReader sr = new StreamReader(fs))
{
while (sr.Peek() >= 0) // reading the old data
{
AddLineToGrid(sr.ReadLine());
index++;
}
}
}
new StreamReader(File.Open(logFilePath,
FileMode.Open,
FileAccess.Read,
FileShare.ReadWrite))
-> this doesn't lock the file.
The problem is when you are writing to the log you are exclusively locking the file down so your StreamReader won't be allowed to open it at all.
You need to try open the file in readonly mode.
using (FileStream fs = new FileStream("myLogFile.txt", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
using (StreamReader sr = new StreamReader(fs))
{
while (!fs.EndOfStream)
{
string line = fs.ReadLine();
// Your code here
}
}
}
I remember doing the same thing a couple of years ago. After some google queries i found this:
FileStream fs = new FileStream(#”c:\test.txt”,
FileMode.Open,
FileAccess.Read,
FileShare.ReadWrite);
i.e. use the FileShare.ReadWrite attribute on FileStream().
(found on Balaji Ramesh's blog)
Have you tried copying the file, then reading it?
Just update the copy whenever big changes are made.
This method will help you to fastest read a text file and without locking it.
private string ReadFileAndFetchStringInSingleLine(string file)
{
StringBuilder sb;
try
{
sb = new StringBuilder();
using (FileStream fs = File.Open(file, FileMode.Open))
{
using (BufferedStream bs = new BufferedStream(fs))
{
using (StreamReader sr = new StreamReader(bs))
{
string str;
while ((str = sr.ReadLine()) != null)
{
sb.Append(str);
}
}
}
}
return sb.ToString();
}
catch (Exception ex)
{
return "";
}
}
Hope this method will help you.