Disk I/O is not and never has been a simple area. The scope for problems is very wide. If your C# I/O code doesn't handle exceptions properly, you'll get to see some very difficult problemsgenerally at inconvenient moments! Before tackling any I/O, it's a good idea to devise an effective exception-management strategy.
Fortunately, the C# language provides a powerful technique in the form of the low-tech try-catch-finally statement. The finally clause provides a good opportunity for deallocating resources, which helps you to avoid leaving old files behind after exceptions occur or after the program finishes.
If you take away just one point from reading this article, make it this: Strive to manage any exception conditions in your own code. Even if you just make a note of the exception, that provides a means to audit the execution at some later time. I've seen cases where code was written with little cognizance taken of exceptions; then, many months later, some weird platform configuration resulted in an uncaughtand troublesomeproduction exception.
An important point to understand about I/O is that larger platforms tend to be more forgiving about poor resource deallocation. The same rule is not true of smaller platforms, such as mobile devices. If your code is not well behaved on small devices, your software may get into difficulties.
C# provides a rich I/O namespace with support for a variety of different design approaches. For example, you can open streams in read-only mode; not exactly super-high-tech, but this approach can help to protect data from inadvertent changes. In this context, read-only access is a useful design pattern to incorporate into your work. In addition, C# provides good support for binary data I/O. There is much scope for study in the C# I/O namespace.