Context
I've written a class to handle settings for my ASP.NET MVC app. However after testing how it handles a malformed/ missing XML file the exception it seems to throw is uncatchable and it repeats endlessly without catching or moving on with execution.
I've disabled the V.S. Debug Dialog popup in the past but again it seems repeat the same segment of code. I do not have a loop anywhere else that calls this property and there is default behavior if the property doesn't return a valid value.
Breakpoints beyond the failing function are not reached, however the breakpoint on or before the XML exception are repeatedly reached...
P.S. there is a lot of failed testing code left over to get a workaround working.
Screenshot:
Screenshot:
EDIT: I must clarify I have tried alternate XML parsing tools, any XMLException here is not caught.
Code ['Setting container' Property]:
private static Settings _singletonSettings;
public static Settings SettingsContainer
{
get
{
if (_singletonSettings == null)
{
_singletonSettings = new Settings();
_singletonSettings .LoadSettings();
}
return _singletonSettings;
}
private set
{
_singletonSettings = value;
}
}
Code ['LoadSettings function']:
public void LoadSettings()
{
string filePath = "Config/Settings.txt";
if (!Directory.Exists(Path.GetDirectoryName(filePath)))
{
Directory.CreateDirectory(Path.GetDirectoryName(filePath));
}
if (File.Exists(filePath))
{
try
{
SettingsContainer = LoadViaDataContractSerialization<Settings>(filePath); // Desperately trying to catch the exception.
}
catch (Exception ex)
{
Log.GlobalLog.WriteError("LoadViaDataContractSerialization() error:\n" + ex.Message + "\nStackTrace: \n" + ex.StackTrace);
}
}
else
{
File.Create(filePath);
}
if (SettingsContainer == null)
{
SettingsContainer = new Settings();
}
}
Code ['LoadViaDataContractSerialization']:
public static T LoadViaDataContractSerialization<T>(string filepath)
{
try
{
T serializableObject;
using (var fileStream = new FileStream(filepath, FileMode.Open))
{
try
{
using (var reader = XmlDictionaryReader.CreateTextReader(fileStream, new XmlDictionaryReaderQuotas())) //All execution stops here with the
{
var serializer = new DataContractSerializer(typeof(T));
serializableObject = (T)serializer.ReadObject(reader, true);
reader.Close();
}
}
catch (XmlException ex)
{
Log.GlobalLog.WriteError("LoadViaDataContractSerialization() XML Fail: Message: " + ex.Message + "\n StackTrace: " + ex.StackTrace);
return default(T);
}
fileStream.Close();
}
return serializableObject;
}
catch (Exception ex)
{
Log.GlobalLog.WriteError("LoadViaDataContractSerialization() Fail: Message: " + ex.Message + "\n StackTrace: " + ex.StackTrace);
return default(T);
}
}
Looks like the issue lay with a lack of understanding in 'return default(T)'.
I'm not sure why it was repeating but by removing the try catch blocks that returned 'default(T)' and responding to the exception 'return new settings()' it allowed the properties value to not be null and function as intended.
Code LoadViaDataContractSerialization:
public static T LoadViaDataContractSerialization<T>(string filepath)
{
T serializableObject;
using (var fileStream = new FileStream(filepath, FileMode.Open))
{
using (var reader = XmlDictionaryReader.CreateTextReader(fileStream, new XmlDictionaryReaderQuotas()))
{
var serializer = new DataContractSerializer(typeof(T));
serializableObject = (T)serializer.ReadObject(reader, true);
reader.Close();
}
fileStream.Close();
}
return serializableObject;
}
Code LoadSettings:
public void LoadSettings()
{
string filePath = "Config/Settings.txt";
if (!Directory.Exists(Path.GetDirectoryName(filePath)))
{
Directory.CreateDirectory(Path.GetDirectoryName(filePath));
}
if (File.Exists(filePath))
{
try
{
SettingsContainer = LoadViaDataContractSerialization<Settings>(filePath);
}
catch (Exception ex) //only exception needed
{
Log.GlobalLog.WriteError("LoadViaDataContractSerialization() error:\n" + ex.Message + "\nStackTrace: \n" + ex.StackTrace);
SettingsContainer = new Settings();//<---this was the fix
}
}
else
{
File.Create(filePath);
}
if(SettingsContainer == null)
{
SettingsContainer = new Settings();
}
}
Thank you to 'Generic Snake' for pointing me at the right place.
If at all returning within try/catch/finally in not considered a structured programming how can I return from the below code block ?
public static string ReadFile()
{
StreamReader streamReader = null;
try
{
try
{
streamReader = new StreamReader(#"C:\Users\Chiranjib\Downloads\C# Sample Input Files\InputParam.txt"); //Usage of the Verbatim Literal
return streamReader.ReadToEnd();
}
catch (FileNotFoundException exfl)
{
string filepath = #"C:\Users\Chiranjib\Downloads\C# Sample Input Files\LogFiles.txt";
if (File.Exists(filepath))
{
StreamWriter sw = new StreamWriter(filepath);
sw.WriteLine("Item you are searching for {0} just threw an {1} error ", exfl.FileName, exfl.GetType().Name);
Console.WriteLine("Application stopped unexpectedly");
}
else
{
throw new FileNotFoundException("Log File not found", exfl);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.StackTrace);
return string.Empty;
}
//Code inside finally gets executed even if the catch block returns when an exception happens
finally
{
//Resource de-allocation happens here
if (streamReader != null)
{
streamReader.Close();
}
Console.WriteLine("Finally block executed");
}
}
catch (FileNotFoundException ex)
{
Console.WriteLine("Log file not found ");
Console.WriteLine("Original exception " + ex.GetType().Name);
Console.WriteLine("Inner Exception " + ex.InnerException.GetType().Name);
}
finally
{
if (streamReader != null)
{
streamReader.Close();
}
Console.WriteLine("Finally block executed");
}
return streamReader.ReadToEnd() ?? string.Empty;
}
Thing is if I at all close the streamReader object before even getting it's value I would not be able to obtain a returned result.
But again it does not allow me to put a return in finally.
Please help me understand and overcome this difficulty in a standard way.
The easiest way for you to resolve this would be to just declare a variable inside your code and then read that out at the end.
For example.
public static string ReadFile()
{
var stringFile = "";
StreamReader streamReader = null;
try
{
try
{
streamReader = new StreamReader(#"C:\Users\Chiranjib\Downloads\C# Sample Input Files\InputParam.txt"); //Usage of the Verbatim Literal
stringFile = streamReader.ReadToEnd();
return stringFile
}
catch (FileNotFoundException exfl)
{
string filepath = #"C:\Users\Chiranjib\Downloads\C# Sample Input Files\LogFiles.txt";
if (File.Exists(filepath))
{
StreamWriter sw = new StreamWriter(filepath);
sw.WriteLine("Item you are searching for {0} just threw an {1} error ", exfl.FileName, exfl.GetType().Name);
Console.WriteLine("Application stopped unexpectedly");
}
else
{
throw new FileNotFoundException("Log File not found", exfl);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.StackTrace);
return string.Empty;
}
//Code inside finally gets executed even if the catch block returns when an exception happens
finally
{
//Resource de-allocation happens here
if (streamReader != null)
{
streamReader.Close();
}
Console.WriteLine("Finally block executed");
}
}
catch (FileNotFoundException ex)
{
Console.WriteLine("Log file not found ");
Console.WriteLine("Original exception " + ex.GetType().Name);
Console.WriteLine("Inner Exception " + ex.InnerException.GetType().Name);
}
finally
{
if (streamReader != null)
{
streamReader.Close();
}
Console.WriteLine("Finally block executed");
}
return stringFile;
}
This should then read out your file by executing the following code
static void Main(string[] args)
{
var file = ReadFile();
Console.WriteLine(file);
Console.ReadLine();
}
I think you could eliminate several of those try/catch sequences and take care of disposing StreamWriter and StreamReader by using "using" statements. Here's an example:
using System;
using System.IO;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
var fileContents = ReadFile();
Console.ReadLine(); // cause program to pause at the end
}
public static string ReadFile()
{
try
{
using (var streamReader = new StreamReader(
#"C:\MyTestFile.txt"))
{
var fileContents = streamReader.ReadToEnd();
Console.WriteLine("File was read successfully");
return fileContents;
}
}
catch (FileNotFoundException fileNotFoundException)
{
LogReadFileException(fileNotFoundException);
}
catch (DirectoryNotFoundException directoryNotFoundException)
{
LogReadFileException(directoryNotFoundException);
}
catch (IOException ioException)
{
LogReadFileException(ioException);
}
// If we get here, an exception occurred
Console.WriteLine("File could not be read successfully");
return string.Empty;
}
private static void LogReadFileException(Exception exception)
{
string logFilePath = #"C:\MyLogFile.txt";
using (var streamWriter = new StreamWriter(logFilePath,
append: true))
{
var errorMessage = "Exception occurred: " +
exception.Message;
streamWriter.WriteLine(errorMessage);
Console.WriteLine(errorMessage);
}
}
}
}
My original related question here (https://stackoverflow.com/questions/17332403/is-there-such-a-c-sharp-method-or-methodology-that-would-equate-to-filealready) was marked as a duplicate, and I used the supposed duplicate
(Is there a way to check if a file is in use?) to try to solve my problem, but I'm still getting flooded with Null Reference Exceptions on some file I/O operations.
Based on that halcyon post of yore, I altered the previous code from this:
public FileQuickRead(string filename)
{
try
{
SR = File.OpenText(filename);
}
catch (Exception ex)
{
CCR.ExceptionHandler(ex, "FileQuickRead.FileQuickRead");
}
. . .
...to this:
public FileQuickRead(string filename)
{
// Added 6/27/2013; adapted from https://stackoverflow.com/questions/876473/is-there-a-way-to-check-if-a-file-is-in-use
try
{
using (Stream stream = new FileStream(filename, FileMode.Open))
{
try
{
SR = File.OpenText(filename);
}
catch (Exception ex)
{
CCR.ExceptionHandler(ex, "FileQuickRead.FileQuickRead");
}
}
}
catch (Exception exc)
{
// If the "using Stream filename" fails
#if TRACE
UtilCE.LogInfo.Add2LogFile(string.Format("Catch block in FileQuickRead caught: {0}", exc.Message));
#endif
}
}
...The log file never contains the "Catch Block" string, so it's getting past the "using filename" but apparently failing on the call to File.OpenText().
Also, it's failing on the other two methods in the class, namely ReadLn and FileClose:
public string FileReadLn()
{
try
{
aLine = SR.ReadLine();
}
catch (Exception ex)
{
CCR.ExceptionHandler(ex, "FileQuickRead.FileReadLn");
}
return aLine;
}
public void FileClose()
{
try
{
SR.Close();
}
catch (Exception ex)
{
CCR.ExceptionHandler(ex, "FileQuickRead.FileClose");
}
}
I get a NullReferenceException on FileQuickRead, FileReadLn, then FileClose, three times in succession.
The only other thing in the class are these global declarations:
private StreamReader SR;
private string aLine;
Callers do so in this way:
fileQuickRead = new FileQuickRead(fn);
// Read the line from the file*
aLine = fileQuickRead.FileReadLn();
. . .
while ((aLine != null) && (aLine != ""))
. . .
aLine = fileQuickRead.FileReadLn();
if (aLine == null)
continue;
. . .
finally
{
fileQuickRead.FileClose();
}
Is the SR.Close() in the FileClose() method not enough? Do I need to do something to completely flush the file, or...???
Great - the only comment in the whole project, and it only divulges the achingly obvious.
Handling files (opening) is an activity particularly prone to error.
If you were to write a function to do this (although trivial), what is the best way to write it in wrt handling errors?
Is the following good?
if (File.Exists(path))
{
using (Streamwriter ....)
{ // write code }
}
else
// throw error if exceptional else report to user
Would the above (although not syntactially correct) a good way to do this?
Accessing external resources is always prone to error. Use a try catch block to manage the access to file system and to manage the exception handling (path/file existence, file access permissions and so on)
First you can verify if you have access to the file, after, if the file exists and between the creation of the stream use a try catch block, look:
public bool HasDirectoryAccess(FileSystemRights fileSystemRights, string directoryPath)
{
DirectorySecurity directorySecurity = Directory.GetAccessControl(directoryPath);
foreach (FileSystemAccessRule rule in directorySecurity.GetAccessRules(true, true, typeof(System.Security.Principal.NTAccount)))
{
if ((rule.FileSystemRights & fileSystemRights) != 0)
{
return true;
}
}
return false;
}
So:
if (this.HasDirectoryAccess(FileSystemRights.Read, path)
{
if (File.Exists(path))
{
try
{
using (Streamwriter ....)
{
// write code
}
}
catch (Exception ex)
{
// throw error if exceptional else report to user or treat it
}
}
else
{
// throw error if exceptional else report to user
}
}
Or you can verify all things with the try catch, and create the stream inside the try catch.
You can use something like this
private bool CanAccessFile(string FileName)
{
try
{
var fileToRead = new FileInfo(FileName);
FileStream f = fileToRead.Open(FileMode.Open, FileAccess.Read, FileShare.None);
/*
* Since the file is opened now close it and we can access it
*/
f.Close();
return true;
}
catch (Exception ex)
{
Debug.WriteLine("Cannot open " + FileName + " for reading. Exception raised - " + ex.Message);
}
return false;
}
One thing that has bugged me with exception handling coming from Python to C# is that in C# there doesn't appear to be any way of specifying an else clause. For example, in Python I could write something like this (Note, this is just an example. I'm not asking what is the best way to read a file):
try
{
reader = new StreamReader(path);
}
catch (Exception)
{
// Uh oh something went wrong with opening the file for reading
}
else
{
string line = reader.ReadLine();
char character = line[30];
}
From what I have seen in most C# code people would just write the following:
try
{
reader = new StreamReader(path);
string line = reader.ReadLine();
char character = line[30];
}
catch (Exception)
{
// Uh oh something went wrong, but where?
}
The trouble with this is that I don't want to catch out of range exception coming from the fact that the first line in the file may not contain more than 30 characters. I only want to catch exceptions relating to the reading of the file stream. Is there any similar construct I can use in C# to achieve the same thing?
Catch a specific class of exceptions
try
{
reader = new StreamReader(path);
string line = reader.ReadLine();
char character = line[30];
}
catch (IOException ex)
{
// Uh oh something went wrong with I/O
}
catch (Exception ex)
{
// Uh oh something else went wrong
throw; // unless you're very sure what you're doing here.
}
The second catch is optional, of course. And since you don't know what happened, swallowing this most general exception is very dangerous.
You could write it like:
bool success = false;
try {
reader = new StreamReader(path);
success = true;
}
catch(Exception) {
// Uh oh something went wrong with opening the file for reading
}
finally {
if(success) {
string line = reader.ReadLine();
char character = line[30];
}
}
You can do this:
try
{
reader = new StreamReader(path);
}
catch (Exception)
{
// Uh oh something went wrong with opening the file for reading
}
string line = reader.ReadLine();
char character = line[30];
But of course, you will have to set reader into a correct state or return out of the method.
Catch more specific exceptions.
try {
reader = new StreamReader(path);
string line = reader.ReadLine();
char character = line[30];
}
catch(FileNotFoundException e) {
// thrown by StreamReader constructor
}
catch(DirectoryNotFoundException e) {
// thrown by StreamReader constructor
}
catch(IOException e) {
// some other fatal IO error occured
}
Further, in general, handle the most specific exception possible and avoid handling the base System.Exception.
You can nest your try statements, too
Exceptions are used differently in .NET; they are for exceptional conditions only.
In fact, you should not catch an exception unless you know what it means, and can actually do something about it.
You can have multiple catch clauses, each specific to the type of exception you wish to catch. So, if you only want to catch IOExceptions, then you could change your catch clause to this:
try
{
reader = new StreamReader(path);
string line = reader.ReadLine();
char character = line[30];
}
catch (IOException)
{
}
Anything other than an IOException would then propagate up the call stack. If you want to also handle other exceptions, then you can add multiple exception clauses, but you must ensure they are added in most specific to most generic order. For example:
try
{
reader = new StreamReader(path);
string line = reader.ReadLine();
char character = line[30];
}
catch (IOException)
{
}
catch (Exception)
{
}
More idiomatically, you would employ the using statement to separate the file-open operation from the work done on the data it contains (and include automatic clean-up on exit)
try {
using (reader = new StreamReader(path))
{
DoSomethingWith(reader);
}
}
catch(IOException ex)
{
// Log ex here
}
It is also best to avoid catching every possible exception -- like the ones telling you that the runtime is about to expire.
Is there any similar construct I can use in C#
to acheive the same thing?
No.
Wrap your index accessor with an "if" statement which is the best solution in your case in case of performance and readability.
if (line.length > 30) {
char character = line [30];
}
After seeing the other suggested solutions, here is my approach:
try {
reader = new StreamReader(path);
}
catch(Exception ex) {
// Uh oh something went wrong with opening the file stream
MyOpeningFileStreamException newEx = new MyOpeningFileStreamException();
newEx.InnerException = ex;
throw(newEx);
}
string line = reader.ReadLine();
char character = line[30];
Of course, doing this makes sense only if you are interested in any exceptions thrown by opening the file stream (as an example here) apart from all other exceptions in the application. At some higher level of the application, you then get to handle your MyOpeningFileStreamException as you see fit.
Because of unchecked exceptions, you can never be 100% certain that catching only IOException out of the entire code block will be enough -- the StreamReader can decide to throw some other type of exception too, now or in the future.
You can do something similar like this:
bool passed = true;
try
{
reader = new StreamReader(path);
}
catch (Exception)
{
passed = false;
}
if (passed)
{
// code that executes if the try catch block didnt catch any exception
}
I have taken the liberty to transform your code a bit to demonstrate a few important points.
The using construct is used to open the file. If an exception is thrown you will have to remember to close the file even if you don't catch the exception. This can be done using a try { } catch () { } finally { } construct, but the using directive is much better for this. It guarantees that when the scope of the using block ends the variable created inside will be disposed. For a file it means it will be closed.
By studying the documentation for the StreamReader constructor and ReadLine method you can see which exceptions you may expect to be thrown. You can then catch those you finde appropriate. Note that the documented list of exceptions not always is complete.
// May throw FileNotFoundException, DirectoryNotFoundException,
// IOException and more.
try {
using (StreamReader streamReader = new StreamReader(path)) {
try {
String line;
// May throw IOException.
while ((line = streamReader.ReadLine()) != null) {
// May throw IndexOutOfRangeException.
Char c = line[30];
Console.WriteLine(c);
}
}
catch (IOException ex) {
Console.WriteLine("Error reading file: " + ex.Message);
}
}
}
catch (FileNotFoundException ex) {
Console.WriteLine("File does not exists: " + ex.Message);
}
catch (DirectoryNotFoundException ex) {
Console.WriteLine("Invalid path: " + ex.Message);
}
catch (IOException ex) {
Console.WriteLine("Error reading file: " + ex.Message);
}
Sounds like you want to do the second thing only if the first thing succeeded. And maybe catching different classes of exception is not appropriate, for example if both statements could throw the same class of exception.
try
{
reader1 = new StreamReader(path1);
// if we got this far, path 1 succeded, so try path2
try
{
reader2 = new StreamReader(path2);
}
catch (OIException ex)
{
// Uh oh something went wrong with opening the file2 for reading
// Nevertheless, have a look at file1. Its fine!
}
}
catch (OIException ex)
{
// Uh oh something went wrong with opening the file1 for reading.
// So I didn't even try to open file2
}
There might not be any native support for try { ... } catch { ... } else { ... } in C#, but if you are willing to shoulder the overhead of using a workaround, then the example shown below might be appealing:
using System;
public class Test
{
public static void Main()
{
Example("ksEE5A.exe");
}
public static char Example(string path) {
var reader = default(System.IO.StreamReader);
var line = default(string);
var character = default(char);
TryElse(
delegate {
Console.WriteLine("Trying to open StreamReader ...");
reader = new System.IO.StreamReader(path);
},
delegate {
Console.WriteLine("Success!");
line = reader.ReadLine();
character = line[30];
},
null,
new Case(typeof(NullReferenceException), error => {
Console.WriteLine("Something was null and should not have been.");
Console.WriteLine("The line variable could not cause this error.");
}),
new Case(typeof(System.IO.FileNotFoundException), error => {
Console.WriteLine("File could not be found:");
Console.WriteLine(path);
}),
new Case(typeof(Exception), error => {
Console.WriteLine("There was an error:");
Console.WriteLine(error);
}));
return character;
}
public static void TryElse(Action pyTry, Action pyElse, Action pyFinally, params Case[] pyExcept) {
if (pyElse != null && pyExcept.Length < 1) {
throw new ArgumentException(#"there must be exception handlers if else is specified", nameof(pyExcept));
}
var doElse = false;
var savedError = default(Exception);
try {
try {
pyTry();
doElse = true;
} catch (Exception error) {
savedError = error;
foreach (var handler in pyExcept) {
if (handler.IsMatch(error)) {
handler.Process(error);
savedError = null;
break;
}
}
}
if (doElse) {
pyElse();
}
} catch (Exception error) {
savedError = error;
}
pyFinally?.Invoke();
if (savedError != null) {
throw savedError;
}
}
}
public class Case {
private Type ExceptionType { get; }
public Action<Exception> Process { get; }
private Func<Exception, bool> When { get; }
public Case(Type exceptionType, Action<Exception> handler, Func<Exception, bool> when = null) {
if (!typeof(Exception).IsAssignableFrom(exceptionType)) {
throw new ArgumentException(#"exceptionType must be a type of exception", nameof(exceptionType));
}
this.ExceptionType = exceptionType;
this.Process = handler;
this.When = when;
}
public bool IsMatch(Exception error) {
return this.ExceptionType.IsInstanceOfType(error) && (this.When?.Invoke(error) ?? true);
}
}
If you happen to be in a loop, then you can put a continue statement in the catch blocks. This will cause the remaining code of that block to be skipped.
If you are not in a loop, then there is no need to catch the exception at this level. Let it propagate up the call stack to a catch block that knows what to do with it. You do this by eliminating the entire try/catch framework at the current level.
I like try/except/else in Python too, and maybe they will get added to C# some day (just like multiple return values were). But if you think about exceptions a little differently, else blocks are not strictly necessary.