17 Oct, 2007 · 11 minutes read
One of the ways of permanent storage of data is through files. A fileis 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 directoryitself 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 pathof 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.
A stream is a sequence of bytes travelling from a sourceto a destinationover a communication medium. Streams can either be inputor 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.
.NET provides a lot of classesfor 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. |
The FileStreamclass resides under the System.IOnamespace 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 objectof the FileStreamclass needs to initialized. The parameterized constructorof 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 parameterto 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.txtcan also be used. Backslash being the escape sequencestarter 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.FileNotFoundExceptionif 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 FileAccesswhich 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 overloadedinto 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 StreamWriterclass which is inheritedfrom the abstract class TextWriterto write a series of characters. After opening the file in the appropriate mode ( Writeor ReadWritein this case), a new object of the StreamWriterclass is created. The object of the FileStreamclass is passed to it, thus associating the stream with the file. After this, the content can be written to the file by using the Writeor the WriteLine method. WriteLineappends 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 Closemethod. 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 Writemethod 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 Flushmethod.
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 StreamReaderclass 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 Readmethod. 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:-
The ReadLinemethod reads a line of characters and returns the result in the form of a string.
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 BaseStreamproperty’s Seekmethod. 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 Originparameter 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 Peekmethod is used to read the next character without consuming it, i.e the file pointer does not move ahead.
The StreamReaderand StreamWriterclasses 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 BinaryReaderand BinaryWriterclasses.
They are very similar to their text counterparts except that no Line ( ReadLineand WriteLine) methods are provided. The BinaryReaderclass 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 StreamReaderclass, we would have to convert the string to integer or double format using the Convert.ToInt32and Convert.ToDoublemethods.
Writing to File
int MyNumber = 69;
BinaryWriter bw = new BinaryWriter(fs);
bw.Write(MyNumber);
Reading from file
BinaryReader br = new BinaryReader(fs);
int MyNumber = br.ReadInt32();
Often we need to browse directories and locate files. Many such operations can be accomplished by using the two classes – DirectoryInfoand FileInfo. Both of these are derived from the FileSystemInfoclass.
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 a DirectoryInfoor FileInfoobject 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");
The following code snippet lists all the files in the C:\Windows directory.
DirectoryInfo di = new DirectoryInfo("C:\\Windows");
FileInfo[] fis = di.GetFiles();
foreach (FileInfo fi in fis)
{
Console.WriteLine(fi.Name);
}