Files & Folders

One of the ways of permanent storage of data is through files. A file is a collection of data stored on a secondary storage device, such as the Hard Disk. Every file has a name associated with it, such as Essay.txt. The name comprises of two parts the base name (in our case ‘Essay’) and the extension (txt). The portion before the period (.) is the base name whereas the one after it is the extension. A file name can also contain multiple periods – Dr. No.avi. The most significant period is always the last one. So, in this case, the base name of the file would be Dr. No and the extension avi.

The extension is what determines the type of the file. For example, a document has an extension of doc while a JPEG Image file has an extension of jpg. The base name is what we specify to identify that particular file.

Files are contained in folders or directories. A directory itself can contain other files and folders, thus forming a hierarchy. Files within a folder (directory) need to have unique names. Files with same base name but different extensions are allowed. So, the file My File.txt and My File.doc can co-exist in a folder. The full path of the file marks its complete address on a machine. For instance, if the file Notepad.exe is contained inside the Windows directory of your C drive, its path would be “C:\Windows\Notepad.exe”. Likewise, if it were to be contained inside the System32 directory which in turn is present in the Windows directory, the full path would be “C:\Windows\System32\Notepad.exe”.

Note: No two files on your computer can have the same full path.

Stream

A stream is a sequence of bytes travelling from a source to a destination over a communication medium. Streams can either be input or output. The input stream is used for reading while the output stream is used for writing.

Note: This stream concept does not just apply to files. It holds true for communication over a network through sockets too.

File System Classes

.NET provides a lot of classes for handling files. These are contained in the System.IO namespace. Listed below are various classes under this namespace.

Class Name Description
FileStream Is used to read from and write to any location within a file.
BinaryReader Is used to read primitive data types in the form of binary data from the stream.
StreamReader Is used to read characters from a byte stream.
StringReader Is used to read data from a string buffer.
BinaryWriter Is used to write primitive data types in the form of binary data to the stream.
StreamWriter Is used to write characters to a byte stream.
StringWriter Is used to write data to a string buffer.
BinaryReader Is used to read primitive data types in the form of binary data from the file stream.
StreamReader Is used to read characters from the a byte stream.
DirectoryInfo Is used to perform operations on directories.
FileInfo Is used to perform operations on files.
FileStream Class

The FileStream class resides under the System.IO namespace and is derived from the abstract class Stream. It supports random access through seeking. Before you begin reading from and writing to a file, an object of the FileStream class needs to initialized. The parameterized constructor of this class allows to create/open files and set up appropriate file sharing modes.

Creating a new file.

FileStream fs = new FileStream
    (
        "TestFile.txt",
        FileMode.Create,
        FileAccess.Write,
        FileShare.Read
    );

Note: The code is spanned across multiple lines for the sake of clarity.

The first parameter to the constructor is the path to the file. In this case the new file will be created in the working directory of the application. A complete path such as C:\Program Files\Maxotek\Tutorials\C-Sharp\Lesson14\TestFile.txt can also be used. Backslash being the escape sequence starter would need to be escaped in the string. The code would look something like:-

FileStream fs = new FileStream
    (
        "C:\\Program Files\\Maxotek\\Tutorials\\C-Sharp\\Lesson14\\TestFile.txt",
        FileMode.Create,
        FileAccess.Write,
        FileShare.Read
    );

Another way of doing this, is to use the @ character before the string. This prevents any escape sequence character as the backslash itself is taken as a normal character.

FileStream fs = new FileStream
    (
        @"C:\Program Files\Maxotek\Tutorials\C-Sharp\Lesson14\TestFile.txt",
        FileMode.Create,
        FileAccess.Write,
        FileShare.Read
    );

The second parameter to the constructor is the FileMode enumeration. It can have any of the following values.

File Mode Description
Create Creates a new file or truncates the existing file.
CreateNew Creates a new file. If the file already exists, throws a System.IO.IOException.
Open Opens an existing file. Throws a System.IO.FileNotFoundException if the file does not exist.
OpenOrCreate Opens an existing file or creates a new one. The difference between this mode and the Create mode is that it does not truncate the file.
Append Opens the file and seeks to the end. A new file is created if the file does not exist.
Truncate Opens an existing file and truncates its content so that the file size becomes zero. Attempting to read in this mode throws an exception.

The third parameter is the FileAccess which specifies whether the file is to be opened for Reading (FileAccess.Read), Writing (FileAccess.Write) or both (FileAccess.ReadWrite).

The last parameter is FileShare mode which states how the file will be shared.

FileShare Mode Description
Read Allows other handles to read from the file.
Write Allows other handles to write to the file.
Delete Allows subsequent deleting of the file.
Inheritable Makes the file handle inheritable to child processes.
None Declines sharing of file. No other process can open the file until it is closed.

Note: The constructor is overloaded into many other forms which take various other types and combinations of parameters. The above form was one of the basic ones.

Writing to the File

We use the StreamWriter class which is inherited from the abstract class TextWriter to write a series of characters. After opening the file in the appropriate mode (Write or ReadWrite in this case), a new object of the StreamWriter class is created. The object of the FileStream class is passed to it, thus associating the stream with the file. After this, the content can be written to the file by using the Write or the WriteLine method. WriteLine appends an end of line to the content. These two methods are highly overloaded to enable almost all built in data types to be directly written.

Once you have done all the writing, make sure you close the file using the Close method. This ensures all the content is physically written to the file. For performance reasons, the write operation is buffered and sometimes the content might not be physically written to the file even after the Write method was called. To force all the buffers to be cleared and all buffered content to be written to the underlying stream (File in our case), use the Flush method.

1
2
3
4
5
6
7
8
9
10
11
12
FileStream fs = new FileStream
    (
        "TestFile.txt",
        FileMode.Create,
        FileAccess.Write,
        FileShare.Read
    );
StreamWriter sw = new StreamWriter(fs);
sw.Write("Hello World");
 
sw.Close();     // Close the Stream
fs.Close();     // Close the File

Reading from a fie

The StreamReader class is used to read a series of characters from a FilStream. This class is derived from the abstract class TextReader. Before reading, the file must be opened in the appropriate mode (Read or ReadWrite). To Read the next character or the next set of characters, use the Read method. This method has two forms. One that does not take any parameters and reads the next character. It returns the byte value of the character. The other one takes three parameters:-

  • An array of characters – The read characters are stored in the variable passed here.
  • The index of the buffer at which to begin writing
  • Maximum number of characters to read

The ReadLine method reads a line of characters and returns the result in the form of a string.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
FileStream fs = new FileStream
    (
        "TestFile.txt",
        FileMode.Open,
        FileAccess.Read,
        FileShare.Read
    );
 
StreamReader sr = new StreamReader(fs);
string str = sr.ReadLine();
while (str != null)
{
    Console.WriteLine(str);
    str = sr.ReadLine();
}
 
sr.Close();     // Close the Stream
fs.Close();     // Close the File

The file pointer can be seeked to any position of the file using the BaseStream property’s Seek method. This method takes two parameters. The first, a byte offset relative to the Origin (second) parameter. This value can be either positive which moves the pointer down the file or negative which moves the file pointer upwards. The second parameter known as the Origin parameter indicates the reference point to obtain the new position. The permissible values are Begin, Current and End.

The following line of code moves the file pointer to the 5th character from the beginning.

sr.BaseStream.Seek(5, SeekOrigin.Begin);

Moves the pointer to the start.

sr.BaseStream.Seek(0, SeekOrigin.Begin);

Moves the pointer to 5 characters ahead of the current position.

sr.BaseStream.Seek(5, SeekOrigin.Current);

Moves the pointer 5 characters backward from the current position.

sr.BaseStream.Seek(-5, SeekOrigin.Begin);

Moves the pointer to the end.

sr.BaseStream.Seek(0, SeekOrigin.End);

The Peek method is used to read the next character without consuming it, i.e the file pointer does not move ahead.

Implementing Binary Read & Write

The StreamReader and StreamWriter classes work with character data. In this mode everything is written as plain text. To implement binary operations, wherein a number such as 327.68 would be written as a float value consuming four bytes and not just as plain text, we need to use the BinaryReader and BinaryWriter classes.

They are very similar to their text counterparts except that no Line (ReadLine and WriteLine) methods are provided. The BinaryReader class also supports data type specific methods such as ReadInt32, ReadDouble, etc. These allow you to directly read the content from the file in the appropriate format. If we were to use the StreamReader class, we would have to convert the string to integer or double format using the Convert.ToInt32 and Convert.ToDouble methods.

Writing to File

1
2
3
int MyNumber = 69;
BinaryWriter bw = new BinaryWriter(fs);
bw.Write(MyNumber);

Reading from file

1
2
BinaryReader br = new BinaryReader(fs);
int MyNumber = br.ReadInt32();
Implementing the Windows File System

Often we need to browse directories and locate files. Many such operations can be accomplished by using the two classes – DirectoryInfo and FileInfo. Both of these are derived from the FileSystemInfo class.

The tables below list some of the commonly used properties and methods corresponding to both of these classes.

Properties of DirectoryInfo Class

Property Description
Attributes Gets or sets attributes associated with the current directory.
CreationTime Gets or sets the Creation time of the directory.
Exists Gets a Boolean value indicating whether the directory exists
FullName Gets a string containing the full path of the directory.
LastAccessTime Gets the last accessed time of the directory.
Name Gets a string containing the name of the directory.

Methods of DirectoryInfo Class

Method Description
Create Creates a directory.
Delete Deletes a directory.
GetDirectories Returns the directories in the current directory. Supports filtering and recursive listing.
GetFiles Returns the file in the current directory.

Properties of FileInfo class

Property Description
Attributes Gets or sets the attributes associated with the current file.
CreationTime Gets or sets the CreationTime of the file.
Directory Gets an instance of the directory to which the file belongs to.
Exists Gets a Boolean value indicating whether the file exists.
Extension Gets a string containing the extension of the file.
FullName Gets a string containing the full path to the file.
LastAccessTime Gets the last access time of the file.
LastWriteTime Gets the time of the last wriiten activity on the file.
Length Gets the length of the file in Bytes.
Name Gets the name of the File.

Methods of FileInfo class

Method Description
Create Creates a new file.
AppendText Appends a text to the file.
Delete Deletes the file.
Open Opens the file.
OpenRead Opens a file in the read-only mode.
Creating Objects

Creating a DirectoryInfo or FileInfo object is very simple. The constructor takes the path to the file.

DirectoryInfo di = new DirectoryInfo("C:\\Windows");
FileInfo fi = new FileInfo("C:\\Windows\\Notepad.exe");
Listing All Files in a Directory

The following code snippet lists all the files in the C:\Windows directory.

1
2
3
4
5
6
DirectoryInfo di = new DirectoryInfo("C:\\Windows");
FileInfo[] fis = di.GetFiles();
foreach (FileInfo fi in fis)
{
    Console.WriteLine(fi.Name);
}
No votes yet.
Please wait...