File I/O with Streams - Part 1 - An Excerpt from Inside C#, Second Edition

Binary Readers and Writers

Recall that the StreamWriter class provides a text-interpolation layer
on top of another stream, such as a FileStream. The StreamWriter.Write
method is heavily overloaded. Thus, not only can we pass it text, we also
can pass it data of type char, int, float, or any other standard type.as
well as an open-ended (params) number of objects and anything derived from
those objects. Of course, this works similarly to the way that Console.Write works: all data of all types is converted to text before being written to the stream. The BinaryWriter class allows you to write data to a stream without this text interpolation so that the data is written in binary form. For example, compare the two files that result from the following code.one written by using StreamWriter, the other with BinaryWriter:

You can open the two output files in Notepad or from the Microsoft Visual
Studio File|Open|File menu. The contents of Foo.txt are shown here:

Hello World 123 45.67

We.d probably accept that the unreadable stuff after "Hello,
World " is the binary numeric data. A quick check of the ASCII
table reveals that the decimal value 123 is the character "{", so
the rest must be the floating-point value. But what.s that unprintable
character at the beginning of the file? If we open the file in Visual
Studio instead of in Notepad, Visual Studio will use a binary/hex editor
when it recognizes nonprintable characters in the file. Take a look at Figure 2.

Now it becomes clearer. The string .Hello, World. is easy to see,
followed by 0x20, which is the space; then the decimal 123, which is
0x7B (the character .{.); followed by another space; then 8 bytes of
floating-point value. As you can see, the value of the very first byte
in the stream is 0x0C, or decimal 12. Anyone with any experience using
strings in Microsoft Visual Basic or using BSTRs in COM development will
recognize this right away. It.s the length of the following string.including
the space at the end.

Naturally, if you plan to write binary data, you.ll want to read back
binary data by using the BinaryReader class, as illustrated in the following
code. When you do so, remember to keep the Close calls at the end.

File System Classes

In addition to the Stream class and its various derivatives, the
.NET Framework classes also offer a set of file system.related classes
for encapsulating information and functionality that's suitable for
processing files and directories. These classes reside in the System.IO
namespace and are listed in Table 2.

Table 2 - File system classes in the .NET Framework Classes

Class

Description

FileSystemInfo

The abstract base class for FileInfo and DirectoryInfo objects, this class contains methods that are common to both file and directory manipulation. Useful when processing a lot of files and directories.

Performs operations on a String that contains file or directory path information.the file or directory doesn't need to exist.

Directory and DirectoryInfo

The FileInfo and DirectoryInfo classes encapsulate information about
files and directories as well as methods, such as Create, Delete, Open,
MoveTo, and CopyTo. These classes two also offer behavior similar to that
of CFile in the Microsoft Foundation Classes (MFC) and fstream in the
Standard C++ library. The following example gets a DirectoryInfo object
from the static Directory.GetCurrentDirectory method and then calls the
DirectoryInfo.GetFiles instance method to get a collection of FileInfo
objects. Finally, we iterate this collection to report on some arbitrary
properties of each file:

In addition to using GetCurrentDirectory, we can construct DirectoryInfo
objects by using a string for the desired path:

dir = new DirectoryInfo(".");
dir = new DirectoryInfo(@"C:\Winnt");

The first example, of course, will produce the same results as calling GetCurrentDirectory will. Another useful method is GetDirectories, which will return as DirectoryInfo objects a collection of subdirectories of the current directory. The common parentage of DirectoryInfo and FileInfo is clear from the following code:

The DirectoryInfo class offers a reasonable set of methods for
creating, deleting, moving, and so on. For instance, we could
create a new directory at some arbitrary location. (In the following
example, the new directory is created within the current directory.)
We could then create a subdirectory within the new directory, set and
then get some attributes, and finally delete both the subdirectory and
the newly created parent directory:

Recall that the library also offers the Directory class, which
exposes only static methods. Thus, in the previous code, we could've
used the static method Directory.Delete instead and achieved the
same results:

//dir.Delete(true);
Directory.Delete(dir.Name, true);

The set of methods offered by the Directory class more or less
parallels the instance methods in the DirectoryInfo class. The
same parallelism is true for the File and FileInfo classes. In
both cases, a couple of additional methods that aren't offered by
the parallel class exist. For instance, the Directory class offers
a GetLogicalDrives method: