Web Development

  Homes arrow Web Development arrow C# Programming: Namespaces and the Base Class...
 Webmaster Tools
Base64 Encoding 
Browser Settings 
CSS Coder 
CSS Navigation Menu 
Datetime Converter 
DHTML Tooltip 
Dig Utility 
DNS Utility 
Dropdown Menu 
Fetch Content 
Fetch Header 
Floating Layer 
htaccess Generator 
HTML Encoder 
HTML Entities 
IP Convert 
Meta Tags 
Password Encryption
Password Strength
Pattern Extractor 
Ping Utility 
Pop-Up Window 
Regex Extractor 
Regex Match 
Scrollbar Color 
Source Viewer 
Syntax Highlighting 
URL Encoding 
Web Safe Colors 
Forums Sitemap 
Weekly Newsletter
Developer Updates  
Free Website Content 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us 
Contact Us 
Site Map 
Privacy Policy 
  >>> SIGN UP!  
  Lost Password? 

C# Programming: Namespaces and the Base Classes Part 4 - File and Folder Operations
By: Developer Shed
  • Search For More Articles!
  • Disclaimer
  • Author Terms
  • Rating: 3 stars3 stars3 stars3 stars3 stars / 2

    Table of Contents:

    Rate this Article: Poor Best 
      Del.ici.ous Digg
      Blink Simpy
      Google Spurl
      Y! MyWeb Furl
    Email Me Similar Content When Posted
    Add Developer Shed Article Feed To Your Site
    Email Article To Friend
    Print Version Of Article
    PDF Version Of Article




    C# Programming: Namespaces and the Base Classes Part 4 - File and Folder Operations
    by Wrox Books

    The .NET base classes include a number of classes that provide a rich set of functionality to do these tasks. These classes are contained in the System.IO namespace. Since the AppWizard doesn't add code to refer to this namespace by default, we add the line using System.IO near the top of the Form1.cs source file for all the samples in this section:
    namespace Wrox.SampleCode.CSharpPreview.ChBaseClasses
    using System;
    using System.Drawing;
    using System.Collections;
    using System.ComponentModel;
    using System.WinForms;
    using System.Data;
    using System.IO;

    Note that (as you can find out from the WinCV tool) these classes are still defined in mscorlib.dll, so we don't need to add any files to the project references.

    Finding Out Information About a File

    Our first file operations sample, which we'll call FileInfo will demonstrate how to get information about a file, such as its last write time, and its size. To do this we use a class, System.IO.File. The code to obtain the information is as follows:

    File fl = new File("C:\\dotNET Book\\Ch8_ADO.doc");
    AddItem("Connected to file : " + fl.Name);
    AddItem("In Folder: " + fl.Directory);
    AddItem("Full path: " + fl.FullName);
    AddItem("Is Directory: " + fl.IsDirectory.ToString());
    AddItem("Is File: " + fl.IsFile);
    AddItem("Last write time: " + fl.LastWriteTime.ToString());
    AddItem("Size in bytes: " + fl.Length);

    This code should be fairly self-explanatory. We construct a File instance by supplying the full path name of the location of the file in the file system, and the File instance then refers to that file, and we can simply read off a number of properties of it. In this case I'm binding to the file for one of the other chapters of this book, the ADO+ chapter. Note that \ by itself is interpreted as the start of an escape sequence in strings in C#, so we need to use \\ to represent a single backslash in the pathname. You can also use an alternative syntax, in which the @ character precedes the string, which indicates that characters should not be escaped. Hence you would write:

    File fl = new File(@"C:\dotNET Book\Ch8_ADO.doc");

    This code gives us this output.

    In general you can use a File object to connect to either a file or a folder, although if you connect to a folder then attempting to access those properties that don't make sense for a folder (such as Length or LastWriteTime) will raise an exception.

    Listing Files in a Folder

    To explore the contents of a folder, we need another base class - in this case the class Directory also in the System.IO namespace. Note that the .NET base classes generally refer to folders as directories in class and method names. This corresponds to normal terminology on web sites and on Unix and Linux machines, as well as on Windows 3.1 when it was around, but can be confusing if you're used to Windows terminology, in which a folder is an item in the file system that contains files, and a directory is a more sophisticated complete information store (such as Active Directory). I'll continue to use the term folder in this chapter, in accordance with normal usage for the Windows file system.

    The following code sample connects to the folder C:\dotNET Book and separately lists the files and folders in it.

    Directory fl = new Directory("C:\\dotNET Book");
    AddItem("Connected to folder: " + fl.Name);
    AddItem("Full path: " + fl.FullName);
    AddItem("Is Directory: " + fl.IsDirectory.ToString());
    AddItem("Is File: " + fl.IsFile);
    AddItem("Files contained in this folder:");
    File [] childfiles = fl.GetFiles();
    foreach (File childfile in childfiles)
    AddItem("  " + childfile.Name);
    AddItem("Subfolders contained in this folder:");
    Directory [] childfolders = fl.GetDirectories();
    foreach (Directory childfolder in childfolders)
    AddItem("  " + childfolder.Name);

    This code starts off by showing that the way of connecting to a folder is the same as for a file, and that the Directory and File classes both share the Boolean IsDirectory and IsFile properties, which can be used to distinguish what the object is if you are unsure. This means that you do not know what an object is, you can for example bind to it as a file, then use the IsDirectory property to check if it is actually a folder - and re-bind to it as a Directory if IsDirectory returns true. The resulting code would look something like this:

    File fl = new File("C:\\DotNET Book");
    if (fl.IsDirectory == true)
    fl = null;
    Directory dr = new Directory("C:\\DotNET Book");
    // process as directory
    // process as file

    In the above code we next use a method, GetFiles() to retrieve a list of the files in the directory. This method returns an array of File instances, each one already bound to a file - so we can use a foreach loop to iterate through the array and carry out whatever processing we need to do on each file. The Directory class has another method, GetDirectories(), which works in exactly the same way as GetFiles(), but returns an array of Directory instances that refer to each subfolder. In both cases in the sample we use these methods to simply display the names of the files and folders.

    This code produces this output on my computer:

    Copying and Deleting files

    The next sample is the one in which we really get to have a bit of fun mucking about with the directory system. As usual, it's a Windows project in which we add the code to the form's constructor, though in this case there's no real output to display.

    We start off by binding to the dotNET Book folder, and we create both a new empty file and a new empty subfolder there. Directory fl = new Directory("C:\\dotNET Book"); fl.CreateSubdirectory("SampleBackups"); fl.CreateFile("MyNewFile.txt");We're not going to write anything to the file yet - we'll do that soon.

    Next we bind to one of the files in the C:\dotNET Book folder, rename it and copy it:

    File adofile = new File("C:\\dotNET Book\\Ch8_ADO.doc");
    adofile.CopyTo("C:\\dotNET Book\\SampleBackups\\Ch8_Backup.doc");

    Note that you should put the complete path in otherwise the file will be copied to the same directory as the executable.

    Now we have a go at deleting things - first the file spec.doc, then the Samples folder.

    File sparefile = new File("C:\\dotNET Book\\spec.doc");
    Directory sparefolder = new Directory("C:\\dotNET Book\\Samples");

    The File.Delete() method doesn't take any parameters. The Directory.Delete() method has two overloads. One (which we haven't demonstrated here) takes no parameters and does a simple delete and the file or directory goes to the recycle bin. The other takes one parameter - a Boolean which indicates whether the delete operation is recursive, which in this case we've specified that it is. If we'd wanted the delete not to be recursive we'd have written:


    In that case if sparefolder contained subfolders an exception would be raised.

    Reading Text Files

    Reading files is quite simple, since Microsoft have provided a large number of classes that represent streams, which may be used to transfer data. Transferring data here can include such things as reading and writing to files, or downloading from the Internet, or simply moving data from one location to another using a stream.

    The available classes are all derived from the class System.IO.Stream, which can represent any stream, and the various classes represent different specializations, for example streams that are specifically geared to reading or writing to files. In general, for the examples in this chapter that involve using streams, there are potentially a number of different ways to write the code, using any of several of the available stream objects. However, in this chapter we'll just present one way that you could perform each of the processes of reading and writing to text and binary files.

    Reading text files is quite simple - for this we're going to use the StreamReader class. The StreamReader represents a stream specifically geared to reading text. We'll demonstrate the process with a sample that reads in and displays the contents of the ReadMe.txt file generated by the developer environment's AppWizard for our earlier EnumFiles sample. The code looks like this.

    File fIn = new File
    ("C:\\dotNET Projects\\Namespaces\\EnumFiles\\ReadMe.txt");
    StreamReader strm = fIn.OpenText();
    // continue reading until end of file
    string sLine;
    sLine = strm.ReadLine();
    while (sLine != null);

    We obtain a StreamReader instance using the OpenText() method of the File class. The StreamReader class contains several methods that either read or peek at differing amounts of data.

    Peeking means looking ahead at the data, but without actually moving through the data. The best way to understand this is by imagining a pointer that indicates which bit of the file you are due to read next. If you read data, then the pointer will be moved to point at the byte following the last byte read, so the next read (or peek) will bring in the next block of data. If you peek at data, the pointer is not changed, so the next read (or peek) will retrieve the same data again.

    The most useful method however for our purposes is ReadLine(), which reads as far as the next carriage return, returning the result in a string. If we have reached the end of the file, ReadLine() does not throw an exception, but simply returns a null reference - so we use this to test for the end of the file. Note that a null reference is not the same as an empty string. If we'd instead applied the condition

    while (sLine != "");

    to the do loop, the loop would have finished the moment we came to a blank line in the file, not at the end of the file. (StreamReader.ReadLine() returns the string without the trailing carriage return and line feed).

    Running this sample produces this output, showing it's correctly read the ReadMe.Txt file:

    Writing Text Files

    Writing text files follows similar principles to reading from them - in this case we use the StreamWriter class.

    What makes writing text files even easier than reading them is that the method we use to write a line of text output followed by a carriage return-line feed, StreamWriter.WriteLine(), has a number of overloads so we don't necessarily need to pass it just text. It will accept a string, an object, a Boolean or several of the numeric types. This can be seen from this code sample, which writes out some text to the blank file we created earlier, MyNewFile.txt.

    StreamWriter strm = new StreamWriter
    ("C:\\dotNET Book\\MyNewFile.txt", false);
    strm.WriteLine("This is some text");
    strm.WriteLine("Next lines are numbers");
    strm.WriteLine("And the next line is a boolean");

    The results of this can be seen in Notepad:

    There are a number of overrides to the constructor of the StreamWriter. The constructor we have picked in our code sample is quite flexible, taking two parameters: the full name of the file, and a Boolean that indicates whether data should be appended to the file. If this is false then the contents of the file will be overwritten by the StreamWriter. In either case, the file will be opened if it already exists or created if it doesn't. This behavior can be customized by using other more complex constructors to the StreamWriter.

    Reading Binary Files

    Once we get to binary files we need to abandon the text-specific StreamReader and StreamWriter classes in place of a more general-purpose class. There are actually two classes that will do the job, System.IO.Stream and System.IO.FileStream. FileStream is designed specifically for reading and writing to files, while Stream is able to transmit data between files or other objects. The two classes work in very similar ways, and for the sake of demonstrating both of them, we'll use Stream for reading data and then use FileStream in the following sample which writes data to a file.

    This sample demonstrates how to use the Stream class to read data. It opens a file and reads it, a byte at a time, each time displaying the numeric value of the byte read.

    File fl = new File("C:\\dotNET Book\\TestReader.txt");
    Stream strm = fl.OpenRead();
    int iNext;
    iNext = strm.ReadByte();
    if (iNext != -1)
    while (iNext != -1);

    We obtain an instance of the Stream class by first instantiating a File object attached to the required file and calling its OpenRead() method. We then read through the file by calling the Stream.ReadByte() method. This method reads the next byte returning its value as an int. If we have reached the end of the file, then -1 is returned, but no exception is thrown - and it is this condition we use to test for the end of the file. Note that the Stream class also has a Read() method which can read a specified number of bytes in one go - I've chosen to use ReadByte() here as it leads to simpler code.

    The file I've tested this code on looks like this - the first few letters of the alphabet followed by three carriage return-line feeds. Although the code will work on any file, I've demonstrated it on a text file because that makes it easier to see visually that the results are correct.

    Running the code on this file produces the following:

    Writing Binary Files

    Although we can use either the Stream or FileStream classes to perform this task, we'll use an instance of FileStream for this sample. This code writes out a short text file that contains the letters FGHIJK followed by a carriage return-line feed combination. Note that again although this code is capable of writing any data, we're using textual data in the sample so that we can easily use Notepad to check that the sample has worked.

    The code looks like this

    byte [] bytes = {70,71,72,73,74,75,13,10};
    FileStream strm = new FileStream
    ("C:\\dotNET Book\\TestWriter.txt", 
    FileMode.OpenOrCreate, FileAccess.Write);
    foreach (byte bNext in bytes)

    We first define an array of bytes that contains the data to be written to the file - in this case the ASCII codes of the characters. True binary data would have simply meant changing some of the values in this array to represent non-printable characters.

    Next we instantiate a FileStream object. The constructor we use takes three parameters: the full pathname of the file, the mode we are using to open it and the access required. The mode and access merit more consideration -- they are enumerated values respectively taken from two further classes in the System.IO namespace: FileMode and FileAccess. The possible values these can take are all self-explanatory. In the case of the mode the possible values are Append, Create, CreateNew, Open, OpenOrCreate and Truncate. For the access they are Read, ReadWrite and Write.

    Finally we use the WriteByte method of the FileStream object to write out each byte before closing the file. Again there is a FileStream.Write method, which can write out a number of bytes at a time and which you may prefer to use. We've stuck with WriteByte because it makes it clearer what is going on as we loop through the array.

    And finally the test whether this code has worked: After running it, opening the new file with Notepad gives this:

    DISCLAIMER: The content provided in this article is not warranted or guaranteed by Developer Shed, Inc. The content provided is intended for entertainment and/or educational purposes in order to introduce to the reader key ideas, concepts, and/or product reviews. As such it is incumbent upon the reader to employ real-world tactics for security and implementation of best practices. We are not liable for any negative consequences that may result from implementing any information covered in our articles or tutorials. If this is a hardware review, it is not recommended to open and/or modify your hardware.

    More Web Development Articles
    More By Developer Shed



    - On Page SEO for New Domains
    - Improve Your Site`s Speed
    - Safari Books Online Review
    - Creating an Estore From the Ground Up
    - Most Common SEO Mistakes Developers Make
    - Making the Most of Your Titles and Meta Desc...
    - Five Ways Using Flash Can Damage Your Site
    - A Web Designer`s Guide to Colors
    - Use Webstarts to Create a Free Site
    - More Than Just Looks. How Your Web Design C...
    - How to Design Content Pages
    - Mint Review
    - Make Your WordPress Website Look Professional
    - How to Create a Mobile Web Site
    - Meta Tags: Still Useful?

    Developer Shed Affiliates


    © 2003-2018 by Developer Shed. All rights reserved. DS Cluster - Follow our Sitemap