-1

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?

R15
  • 13,982
  • 14
  • 97
  • 173
  • 3
    Try Catch maybe? – Berkay Yaylacı May 06 '20 at 09:56
  • I think the answer from @Rahul is better, since try-catch shouldn't be used for flow control , right? – Roland Deschain May 06 '20 at 09:58
  • @RolandDeschain Know the rules but also know when to break them. :D – Fildor May 06 '20 at 10:00
  • @Fildor sure, but what speaks against his solution in this case? – Roland Deschain May 06 '20 at 10:02
  • @RolandDeschain It ought to be in a try...catch as well as checking if the file exists, in case the user disconnects the disk drive or something unfortunate happens to the file. – Andrew Morton May 06 '20 at 10:06
  • @RolandDeschain I meant kind of what Andrew said. If you allow for an "alternative attempt" you "kind of" do flow control via exception. But it's a grey area because that _is_ the _exception_ ... see what I mean? So it's not really "breaking the rule" it's just a little bending. – Fildor May 06 '20 at 10:49

4 Answers4

6

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
}
Rahul
  • 76,197
  • 13
  • 71
  • 125
  • There could be a race condition that will still trigger an exception in the line `FileStream fs = ...`: the file could be deleted immediately after its existence check. In this case the flow control moves to the catch block, skipping the check of the second location. – Luca Cremonesi May 11 '20 at 15:57
5

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;
    }
}
Haytam
  • 4,643
  • 2
  • 20
  • 43
2

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);
 }
SomeBody
  • 7,515
  • 2
  • 17
  • 33
1

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)
    {}
}    
StepUp
  • 36,391
  • 15
  • 88
  • 148