File, Directory, Stream and Registry Classes in .Net
The System.IO namespace contains many file and directory related classes. Five of these important classes that let us manipulate and explore files and directories are:
Examples: (Files are always tied to stream objects for
reading or writing to them)
Stream fs = File.Open(@"c:\temp\t1.txt",FileAccess.Read);
File.Copy(@"c:\temp\source.txt",@"c:\temp\dest.txt");
Example:
FileInfo
fr = new FileInfo(@"c:\temp\t1.txt");
// input file
StreamReader
reader = fr.OpenText(); // OpenText returns StreamReader
// Test to
see if file exists
string
file = “c:\\temp\\t1.txt”;
FileInfo
fileUnderTest = new FileInfo(file);
if (fileUnderTest.Exists)
{
//
do something with the file
return;
}
// otherwise not a file or directory
throw new
FileNotFoundException("No file called:"+file);
Example:
Directory.CreateDirectory(@"c:\\temp");
Example:
dirName
= "c:\\temp";
DirectoryInfo
dir = new DirectoryInfo(dirName);
if (!dir.Exists)
throw new
DirectoryNotFoundException
("directory
does not exist:"+dirName);
// fill the directory listbox
foreach(DirectoryInfo di in
dir.GetDirectories())
lstFolders.Items.Add(di.Name);
// fill the Files listbox
foreach(FileInfo fi in
dir.GetFiles())
lstFiles.Items.Add(fi.Name);
string fpath = Path.Combine(@”c:\temp”, “t1.txt”);
We will create a windows application to view a given directory’s contents and to list the different attributes of a file in it.
Example: Create a new windows type project. Name the project FileDirInfo. Place some labels, buttons and text boxes on the form as shown below.
The names of the top text box where the directory name will be typed is: txtDirectory. The button next to it has a name of btnExamine, and the “Move Up” button has a name of btnMoveUp. The filter text box has a name of txtFilter and the button next to it has a name of btnFilter.
The two list boxes in the middle of the form have names of lstFiles and lstFolders. The four labels with dark boundaries (BorderStyle property of FixedSingle) are contained inside a group box. These labels have names of lblFileName, lblFileSize, lblCreationTime, and lblLastAccessed respectively. Finally the exit button has a name of btnExit.
Add the following using statement close to the top of the form code.
using System.IO;
Add the following data member (shown in bold) to the form class:
public class Form1 : System.Windows.Forms.Form
{
private string currentDirectory;
Exercise: Write a control clearing function called “ClearAllControls( )” that will clear out every control except the fixed type of labels, and except the top text box that contains the directory to be examined.
Hint: Use the Controls collection in the form. Remember the controls in the group box need to handled as a separate Controls collection in the group box. If you are unsuccessful at writing the code, the solution is given at the end of this handout.
private void ClearAllControls()
{
// instead explicitly clearing a control by
// its name, it is better to do it through
// forms collection. This way, if you added
// a control in the future, it will get cleared.
// do not clear top edit box that contains
directory name
}
Write a general purpose
function called “DisplayFiles(string dirName )” that takes the directory name
as a parameter and populates the two list boxes (lstFiles and lstFolders with
the files and folders contained within the parameter dirName directory i.e.,
the lstFiles list box is populated with the files in the dirName directory and
the lstFolders list box is populated with the folders in the dirName directory.
The code for this function
will look as:
private void
DisplayFiles(string dirName)
{
// test to see if directory exists
DirectoryInfo
dir = new DirectoryInfo(dirName);
if (!dir.Exists)
throw new
DirectoryNotFoundException
("directory
does not exist:"+dirName);
// fill the directory listbox
foreach(DirectoryInfo di in
dir.GetDirectories())
lstFolders.Items.Add(di.Name);
// fill the Files listbox
foreach(FileInfo fi in
dir.GetFiles())
lstFiles.Items.Add(fi.Name);
}
Now that we have our two
support functions (ClearAllControls( ) and DisplayFiles( ), we can write the
code for the different event handlers.
Write the following event
handler for the “Examine Directory” button (btnExamine) event handler.
private void btnExamine_Click(object
sender, System.EventArgs e)
{
try
{
string dir = txtDirectory.Text;
ClearAllControls();
DirectoryInfo
dinfo = new DirectoryInfo(dir);
if (dinfo.Exists)
{
currentDirectory
= dir;
DisplayFiles(dinfo.FullName);
// populate left list box
return; // valid directory
}
// otherwise check to see if it is a file
FileInfo
fileTest = new FileInfo(dir);
if (fileTest.Exists)
{
DisplayFiles(fileTest.Directory.FullName);
int index = lstFiles.Items.IndexOf(fileTest.Name);
lstFiles.SetSelected(index,true);
return;
}
// otherwise not a file or directory
throw new
FileNotFoundException(
"No
file or directory called:"+dir);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
When someone selects a file
from the Files list box (lstFiles), we need to display the different properties
of this file in the labels in the group box. The event that is generated when
someone selects from a list box is called “SelectedIndexChanged”. Write this
event handler for the Files list box. The code in the handler will look as:
private void
lstFiles_SelectedIndexChanged(object sender,
System.EventArgs e)
{
string fname = lstFiles.SelectedItem.ToString();
string fullFileName = Path.Combine(currentDirectory,fname);
FileInfo
finfo = new FileInfo(fullFileName);
lblFileSize.Text
= finfo.Length.ToString();
lblFileName.Text
= finfo.Name;
lblCreationTime.Text
= finfo.CreationTime.ToString();
lblLastAccessed.Text
= finfo.LastAccessTime.ToString();
}
Similarly write an event
handler for the Folders list box so that if someone selects a folder from it,
the contents of the Files list box are changed appropriately. The
SelectedIndexChanged event for the Folders list box will appear as:
private void
lstFolders_SelectedIndexChanged(object sender,
System.EventArgs e)
{
string dirName = lstFolders.SelectedItem.ToString();
string fullDirName = Path.Combine(
currentDirectory,dirName);
ClearAllControls();
txtDirectory.Text
= fullDirName;
currentDirectory
= fullDirName;
DisplayFiles(fullDirName);
}
Write the following event
handler for the “Move Up” button which allows the directory being examined to
be changed to the parent directory.
private void
btnMoveUp_Click(object sender, System.EventArgs
e)
{
try
{
ClearAllControls();
string parentDir = new
FileInfo(currentDirectory).DirectoryName; // returns parent
txtDirectory.Text
= parentDir;
currentDirectory
= parentDir;
DisplayFiles(parentDir);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
The handler for the exit button will have the
code of:
Application.Exit(
);
Build and test the application.
Enhancing the Application:
Add
three more labels with border style of “Fixed Single” in the right hand portion
of the group box as shown above. Assign
names of lblDirCreationTime, lblDirLastAccessed, and lblDirLastWriteTime to the
three labels. Add three more labels next to these with default names. The text
properties of the labels will be as shown above.
Exercise: Modify the code in the DisplayFiles( )
function so that it displays the attributes of the directory selected in the
three labels just created. If you are unable to accomplish this, the solution is
given at the end of this handout.
Exercise: Write the code for the Filter List button
event handler, so that it lists only the files in the list box (lstFiles)
whose extension matches the text in the txtFilter text box. If you are
unable to accomplish this, the solution is given at the end of this handout.
Deleting a File:
The
File class has a simple Delete method that can be called to delete a file. It
is always a good idea to confirm the deletion of a file from the user before
actually deleting the file. Place a button at the left bottom of the form
(below the group box) with a text property of “Delete Selected File” and a name
of btnDeleteFile. Type the following code for the delete file button
handler.
private void
btnDeleteFile_Click(object sender,
System.EventArgs e)
{
try
{
string selFile = lstFiles.SelectedItem.ToString();
string selFileFullName =
Path.Combine(currentDirectory,selFile);
string question = "Really Delete File? "+
selFileFullName;
if (MessageBox.Show(question,"Delete
File?",
MessageBoxButtons.YesNo)
== DialogResult.Yes)
{
File.Delete(selFileFullName);
// remove this file from the
DisplayFiles(currentDirectory);
}
}
catch(Exception ex)
{
MessageBox.Show("Unable
to Delete File:" + ex.Message);
}
}
Moving a File:
The
File class has a Move method that takes the source file name and the
destination file name as parameters.
It is always a good idea to confirm the moving of a file from the user
before actually moving the file. Place a button a text box at the middle bottom
of the form (below the group box) with a name property of “txtMoveFile”. Place
a button next to it with the text property of “Move Selected File” and a name
of btnMoveFile. Write the following code for the move file button handler.
private void
btnMoveFile_Click(object sender,
System.EventArgs e)
{
try
{
string selFile = lstFiles.SelectedItem.ToString();
string selFileFullName =
Path.Combine(currentDirectory,selFile);
string question = "Really Move File? "+
selFileFullName;
if (MessageBox.Show(question,"Move File?",
MessageBoxButtons.YesNo)
== DialogResult.Yes)
{
string destFolder = txtDestFolder.Text;
DirectoryInfo
dir = new DirectoryInfo(destFolder);
if (!dir.Exists)
throw new
DirectoryNotFoundException
("Dest.
directory does not exist:"+dir.FullName.ToString());
string destFileName =
Path.Combine(destFolder,selFile);
File.Move(selFileFullName,destFileName);
// refresh the list box
DisplayFiles(currentDirectory);
}
}
catch(Exception ex)
{
MessageBox.Show("Unable
to Move File:" + ex.Message);
}
}
Copying a File:
The
File class also contains a Copy method that allows you to copy one file to
another file.
Exercise: Add another button to the form with a text
property of “Copy Selected File” and a name of btnCopyFile. The same txtDestFolder
text box can be used to specify the destination folder for copying the file.
The code for the Copy File button handler will be very similar to the Move File
handler. The solution to this exercise is given at the end of this handout.
The final form of the application is shown
below.
Reading Writing to Files
The
important concept in reading and writing to files is that the file I/O is done
using streams. .Net has many different kinds of stream classes that allow you
to read/write to files, network sockets, and memory.
Of
these, the Stream class is an abstract class that provides binary
reading and writing of data. Some of the important methods of the stream class
are: Read(), Write(), Close() and Flush().
Example: Binary copying of files.
Create a new C# console type application.
Name the project BinaryFileCopy. Name the default class StreamTest. Include the
following using statement close to the top of the code area.
Using
System.IO;
Type the following code in the main method.
static
void Main(string[]
args)
{
int
buffSize = 4096;
Stream inStream = File.OpenRead(@"c:\temp\default.asp");
Stream outStream =
File.Open(@"d:\temp\default.asp",FileMode.OpenOrCreate);
Byte[] buffer = new Byte[buffSize] ;
// buffer size
int
numBytesRead;
while
((numBytesRead = inStream.Read(buffer,0,buffSize)) > 0)
{
outStream.Write(buffer,0,numBytesRead);
}
inStream.Close();
outStream.Close();
}
Build and test the program.
Buffered Streams:
Since
the disk access is time consuming, the operating system reads the disk in
blocks of bytes (even though you may be interested in reading only one byte).
Thus when you have large amount of data to read in small chunks at a time, you
can create a buffered stream on top of the regular stream so that your next
read will come from the buffer, thereby improving the performance of your
application greatly.
When
writing to a file using buffered stream, you should always flush the buffer
before closing the stream otherwise the bytes left in the buffer may not be
written to the file.
Example: We will modify the previous example to work
with buffered streams.
The modifications in the previous code are
shown below in bold.
static void Main(string[] args)
{
int buffSize = 4096;
Stream
inStream = File.OpenRead(@"c:\temp\default.asp");
Stream
outStream = File.Open(@"d:\temp\default.asp",FileMode.OpenOrCreate);
BufferedStream
inbuffStream =
new BufferedStream(inStream);
BufferedStream
outbuffStream =
new BufferedStream(outStream);
Byte[]
buffer = new Byte[buffSize] ; // buffer size
int numBytesRead;
while ((numBytesRead = inbuffStream.Read(buffer,0,buffSize))
> 0)
{
outbuffStream.Write(buffer,0,numBytesRead);
}
outbuffStream.Flush();
inbuffStream.Close();
outbuffStream.Close();
}
There
is a FileStream class that also supports binary reads and writes. It includes
random access capability for reading/writing to files and also supports
asynchronous access where the call to the Read or Write methods does not block.
This way the user does not need to create any threads for long read/write
operations. The asynchronous read/write will notify the program when the
operation is completed.
Examples:
FileStream
fsw = new
FileStream(@"d:\temp\t1.txt", FileMode.Create, FileAccess.Write);
byte b1 = 65;
fsw.Write(b1);
// you can also write a array of bytes
byte [] bArr = new
Byte[100];
fsw.Write(bArr,0,50);
// similarly you can read bytes from a file
FileStream
fsr = new
FileStream(@"d:\temp\t1.txt", FileMode.Open, FileAccess.Read);
fsr.Read(bArr,0,50);
fsr.Close();
fsw.Close();
Reading and Writing to Text
Files:
For
reading and writing to Text files, generally the StreamReader and StreamWriter
classes are used. These classes have ReadLine( ) and WriteLine( ) methods that
can read or write an entire line of text from the file. You can further parse
this line if you needed to read the specific type of data contained in the
file.
Another
benefit of the StreamReader and StreamWriter classes is that you do not have to
worry about the type of character encoding used in the file. The Windows 9x
operating system uses ASCII encoded text files whereas in WindowsXP and 2000,
Unicode encoding is used. You can also specify or find out the encoding used in
a file with the StreamReader or StreamWriter classes.
e.g.,
StreamWriter
fsw = new StreamWriter(
@"c:\temp\t2.txt",
false, System.Text.Encoding.Unicode);
Example: Create a console type application called FileIO. Modify the default class in it to look as:
using System;
using System.IO; // for file
related classes
namespace FileIO
{
/// <summary>
/// Summary description for
Class1.
/// </summary>
class Class1
{
/// <summary>
/// The main entry point
for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
FileInfo
fr = new FileInfo(@"c:\temp\t1.txt");
// input file
StreamReader
reader = fr.OpenText(); // OpenText returns StreamReader
string sline; string [] substrings;
char [] separators = {' ', ',','\t'};
string name; int ID; float gpa; // data
for one line
// e.g., Baker
35792 3.45
StreamWriter writer = new StreamWriter(@"c:\temp\t2.txt",false);
// false means do not append to existing file
sline = reader.ReadLine();
while (sline != null)
{
substrings
= sline.Split(separators,3); // 3 maximum size to
split
name = substrings[0];
ID = int.Parse(substrings[1]);
gpa = float.Parse(substrings[2]);
Console.WriteLine("{0} {1} {2}", name,ID,gpa);
writer.WriteLine("{0} {1} {2}",name, ID, gpa);
sline = reader.ReadLine();
}
writer.Flush();
writer.Close();
}
}
}
To test the above program, first create a
file using notepad called “t1.txt” in the c:\temp directory. The data in this
file will look as:
Baker
35762 3.35
Simpson 45928 2.89
Kim 87231 3.77
Solution to Exercises:
Clearing All Controls (except fixed labels and top edit box):
private void
ClearAllControls()
{
// instead explicitly clearing a control by
// its name, it is better to do it through
// forms collection. This way, if you added
// a control in the future, it will get cleared.
foreach (Control ctl in
this.Controls)
{
string ctlName = ctl.Name;
string ctlPrefix = ctlName.Substring(0,3); // for lbl
if ((ctl is TextBox)
&& (ctlName != "txtDirectory"))
{ // if it is not
the top directory textbox
TextBox
txtT1 = (TextBox) ctl;
txtT1.Text
= "";
}
if (ctlPrefix == "lbl") // output labels
{
Label
L1 = (Label) ctl;
L1.Text
= "";
}
if (ctl is ListBox)
{
ListBox
Lb = (ListBox) ctl;
Lb.Items.Clear();
}
// group box is a control container
// so we need to look inside the group
if (ctlPrefix == "gro")
{
foreach (Control ct in
ctl.Controls)
{
string ctPrefix = ct.Name.Substring(0,3);
if (ctPrefix == "lbl")
{
Label
lb = (Label) ct;
lb.Text
= "";
}
}
}
}
Displaying Selected Directory
Attributes:
Add the bolded lines to the DisplayFiles function
private void
DisplayFiles(string dirName)
{
// test to see if directory exists
DirectoryInfo
dir = new DirectoryInfo(dirName);
if (!dir.Exists)
throw new
DirectoryNotFoundException
("directory
does not exist:"+dirName);
// fill the directory listbox
lstFolders.Items.Clear();
foreach(DirectoryInfo di in
dir.GetDirectories())
lstFolders.Items.Add(di.Name);
// fill the directory properties labels in the group box
lblDirCreationTime.Text
= dir.CreationTime.ToString();
lblDirLastAccessed.Text
= dir.LastAccessTime.ToString();
lblDirLastWriteTime.Text
= dir.LastWriteTime.ToString();
// fill the Files listbox
lstFiles.Items.Clear();
foreach(FileInfo fi in
dir.GetFiles())
lstFiles.Items.Add(fi.Name);
}
Filtering Files of a certain
Extension:
Code for the Filter List Button:
private void
btnFilter_Click(object sender, System.EventArgs
e)
{
try
{
string filter = “.” + txtFilter.Text;
lstFiles.Items.Clear();
// clear Files list box
DirectoryInfo
dir = new DirectoryInfo(currentDirectory);
if (!dir.Exists)
throw new
DirectoryNotFoundException
("directory
does not exist:"+dir.FullName.ToString());
// fill the Files listbox
foreach(FileInfo fi in
dir.GetFiles())
{
if (fi.Extension == filter)
lstFiles.Items.Add(fi.Name);
}
//clear file info labels in the group box
lblFileName.Text
= "";
lblFileSize.Text
= "";
lblLastAccessed.Text
= "";
lblCreationTime.Text
= "";
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Copying
a File to another Folder:
private void
btnCopyFile_Click(object sender,
System.EventArgs e)
{
try
{
string selFile = lstFiles.SelectedItem.ToString();
string selFileFullName =
Path.Combine(currentDirectory,selFile);
string question = "Really Copy File? "+
selFileFullName;
if (MessageBox.Show(question,"Copy File?",
MessageBoxButtons.YesNo)
== DialogResult.Yes)
{
string destFolder = txtDestFolder.Text;
DirectoryInfo
dir = new DirectoryInfo(destFolder);
if (!dir.Exists)
throw new
DirectoryNotFoundException
("Dest.
directory does not exist:"+dir.FullName.ToString());
string destFileName =
Path.Combine(destFolder,selFile);
File.Copy(selFileFullName,destFileName);
// refresh the list box
DisplayFiles(currentDirectory);
}
}
catch(Exception ex)
{
MessageBox.Show("Unable
to Copy File:" + ex.Message);
}
}