File Handling In C# .NET

Abstract

This article illustrates how to perform tasks involving reading and writing files from various partitions using the C# .Net programming API. In particular, it covers exploring the directory structure, determining what files and folders are present, and also does other file-related operations such as moving, copying, and deleting objects from the disk. The core purpose of this article is to explore types defined in the System.IO namespace and to provide an understanding of various ways to read from and write to character-based, binary-based, and string-based data stores.

The Anatomy of the File System

The System.IO namespace provides four classes that allow you to manipulate individual files, as well as interact with a machine directory structure. The Directory and File directly extend the System. Object and supports the creation, copying, moving, and deletion of files using various static methods. They only contain static methods and are never instantiated. The FileInfo and DirecotryInfo types are derived from the abstract class FileSystemInfo type and they are typically, employed for obtaining the full details of a file or directory because their members tend to return strongly typed objects. They implement roughly the same public methods as a Directory and a File but they are stateful and the members of these classes are not static.

Anatomy of the file system

In the .NET framework, the System.IO namespace is the region of the base class libraries devoted to file-based input and output services. Like any namespace, the System.IO namespace defines a set of classes, interfaces, enumerations, structures, and delegates. The following table outlines the core members of this namespace

Class Types Description
Directory/ DirectoryInfo These classes support the manipulation of the system directory structure.
DriveInfo

This class provides detailed information regarding the drives that a given machine has.

FileStream This gets you random file access with data represented as a stream of bytes.
File/FileInfo These sets of classes manipulate a computer's files.
Path It performs operations on the System. String types that contain file or directory path information in a platform-neutral manner.
BinaryReader/ BinaryWriter These classes allow you to store and retrieve primitive data types as binary values.
StreamReader/StreamWriter Used to store textual information in a file.
StringReader/StringWriter These classes also work with textual information. However, the underlying storage is a string buffer rather than a physical file.
BufferedStream This class provides temp storage for a stream of bytes that you can commit to storage at a later time.

The System.IO provides a class DriveInfo to manipulate the system drive-related tasks. The DriveInfo class provides numerous details such as the total number of drives, calculation of total hard disk space, available space, drive name, ready status, types, and so on. Consider the following program that shows the total disk drives

DriveInfo[] di = DriveInfo.GetDrives();
Console.WriteLine("Total Partitions");

foreach (DriveInfo items in di)
{
    Console.WriteLine(items.Name);
}

The following code snippets perform the rest of the DriveInfo class method operations in detail. It displays specific drive full information.

using System;
using System.IO;
namespace DiskPartition
{
    class Program
    {
        static void Main(string[] args)
        {
            DriveInfo[] di = DriveInfo.GetDrives();

            Console.WriteLine("Total Partitions");
            Console.WriteLine("---------------------");
            foreach (DriveInfo items in di)
            {
                Console.WriteLine(items.Name);
            }
            Console.Write("\nEnter the Partition::");
            string ch = Console.ReadLine();
            DriveInfo dInfo = new DriveInfo(ch);
            Console.WriteLine("\n");
            Console.WriteLine("Drive Name::{0}", dInfo.Name);
            Console.WriteLine("Total Space::{0}", dInfo.TotalSize);
            Console.WriteLine("Free Space::{0}", dInfo.TotalFreeSpace);
            Console.WriteLine("Drive Format::{0}", dInfo.DriveFormat);
            Console.WriteLine("Volume Label::{0}", dInfo.VolumeLabel);
            Console.WriteLine("Drive Type::{0}", dInfo.DriveType);
            Console.WriteLine("Root dir::{0}", dInfo.RootDirectory);
            Console.WriteLine("Ready::{0}", dInfo.IsReady);
            Console.ReadKey();
        }
    }
}

After compiling this program, it displays nearly every detail of disk drives and a specific drive as in the following

Details of disk drives

Working with Directories

The .NET framework provides two rudimentary classes, DirectoryInfo and Directory, to do directory-related operations such as creation and deletion.

Directory Info Class

The DirectoryInfo class contains a set of members for the creation, deletion, moving, and enumeration of directories and subdirectories. Here, in the following code sample, display the information related to the temp directory.

DirectoryInfo di = new DirectoryInfo(@"D:\temp");

Console.WriteLine("*******Directory Informations*******\n\n");
Console.WriteLine("Full Name={0}", di.FullName);
Console.WriteLine("Root={0}", di.Root);
Console.WriteLine("Attributes={0}", di.Attributes);
Console.WriteLine("Creation Time={0}", di.CreationTime);
Console.WriteLine("Name={0}", di.Name);
Console.WriteLine("Parent={0}", di.Parent);

The previous code produces the information related to the temp directory located in the D drive as in the following.

Temp directory

Typically, we make the assumption that the path passed in the constructor of the DirectoryInfo class physically exists. However, if you attempt to interact with a nonexistent directory then the CLR will throw an exception. So, we need to create a directory first to handle the exceptions that occur as in the following.

DirectoryInfo di = new DirectoryInfo(@"D:\temp\xyz");
di.Create();

We can also programmatically extend a directory structure using the CreateSubdirectory() method. The following code sample first creates a subdirectory in D drive then in D:\ajay\ as in the following.

DirectoryInfo di = new DirectoryInfo(@"D:\");
di.CreateSubdirectory("ajay");
di.CreateSubdirectory(@"ajay\ajay11");

Directory Class

The Directory class provides nearly the same functionality as DirecotryInfo. The Directory class typically returns string data rather than strongly typed DirectoryInfo objects. The following sample deletes the directory and subdirectory in the D drive.

static void Main(string[] args)
{
    DirectoryInfo di = new DirectoryInfo(@"d:\abc");
    Console.WriteLine("Name:{0}", di.FullName);

    Console.Write("Are you sure to Delete:");
    string str = Console.ReadLine();
    if (str == "y")
    {
        Directory.Delete(@"d:\abc", true);
    }
    Console.Write("Deleted.....");
}

Reading and Writing to Files

Reading and writing operations are done using a File object. The following code snippet reads a text file located in the machine somewhere.

private void button1_Click(object sender, EventArgs e)
{
    try
    {
        textBox2.Text = File.ReadAllText(txtPath.Text);
    }
    catch (FileNotFoundException)
    {
        MessageBox.Show("File not Found....");
    }
}

Here, first the user interface asks the user to enter the path of the file that he wanted to display. Later that path is passed to the File method ReadAllText() method that reads all the text integrated in the file and displays it over the text box.

Besides reading a file, we can write some contents over an existing text file by the File class WriteAllTest() method as in the following.

 

File.WriteAllText(@"d:\test.txt", textBox2.Text);

It takes a path to save the file and content input method medium such as a text box or any other control. The following images depict a text file reading by entering its corresponding path.

File reading and writing

Stream

The .NET provides many objects such as FileStream, StreamReader/Writer, and BinaryReader/Writer to read from and write data to a file. A stream represents a chunk of data flowing between a source and a destination. Stream provides a common way to interact with a sequence of bytes regardless of what kind of devices store or display the bytes. The following table provides common stream member functions.

Methods Description
Read()/ ReadByte() Read a sequence of bytes from the current stream.
Write()/WriteByte() Write a sequence of bytes to the current stream.
Seek() Sets the position in the current stream.
Position() Determine the current position in the current stream.
Length() Return the length of the stream in bytes.
Flush() Updates the underlying data source with the current state of the buffer and then clears the buffer.
Close() Closes the current stream and releases any associated stream resources.


FileStream

A FileStream instance is used to read or write data to or from a file. To construct a FileStream, first, we need a file that we want to access. Second, the mode that indicates how we want to open the file. Third, the access indicates how we want to access a file. And finally, the shared access specifies whether you want exclusive access to the file.

Enumeration Values
FileMode Create, Append, Open, CreateNew, Truncate, OpenOrCreate
FileAccess Read, Write, ReadWrite
FileShare Inheritable, Read, None, Write, ReadWrite

The FileStream can read or write only a single byte or an array of bytes. You will be required to encode the System. String type into a corresponding byte array. The System.Text namespace defines a type named encoding that provides members that encode and decode strings to an array of bytes. Once encoded, the byte array is persisted to a file with the FileStream.Write() method. To read the bytes back into memory, you must reset the internal position of the stream and call the ReadByte() method. Finally, you display the raw byte array and the decoded string to the console.

using (FileStream fs = new FileStream(@"d:\ajay123.doc", FileMode.Create))
{
    string msg = "first program";
    byte[] byteArray = Encoding.Default.GetBytes(msg);
    fs.Write(byteArray, 0, byteArray.Length);
    fs.Position = 0;
    byte[] rFile = new byte[byteArray.Length];
    for (int i = 0; i < byteArray.Length; i++)
    {
        rFile[i] = (byte)fs.ReadByte();
        Console.WriteLine(rFile[i]);
    }
    Console.WriteLine(Encoding.Default.GetString(rFile));
}

BinaryReader and BinaryWriter

The BinaryReader and Writer class allows you to read and write discrete data types to an underlying stream in a compact binary format. The BinaryWriter class defines a highly overloaded Write method to place a data type in the underlying stream.

Members Description Class
Write Write the value to the current stream BinaryWriter
Seek Set the position in the current stream BinaryWriter
Close Close the binary reader BinaryWriter
Flush Flush the binary stream BinaryWriter
PeekChar Return the next available character without advancing the position in the stream BinaryReader
Read Read a specified set of bytes or characters and store them in the incoming array. BinaryReader

The following sample first writes several data contents to a new champu.dat file using BinaryWriter. Later, to read the data, the BinaryReader class employs several methods.

class Program
{
    static void Main(string[] args)
    {
        // writing
        FileInfo fi = new FileInfo("champu.dat");
        using (BinaryWriter bw = new BinaryWriter(fi.OpenWrite()))
        {
            int x = 007;
            string str = "hello champu ,one day you will become doomkatu";

            bw.Write(x);
            bw.Write(str);
        }

        // Reading
        FileInfo f = new FileInfo("champu.dat");
        using (BinaryReader br = new BinaryReader(fi.OpenRead()))
        {
            Console.WriteLine(br.ReadInt32());
            Console.WriteLine(br.ReadString());
        }
        Console.ReadLine();
    }
}

StringReader and StringWriter

We can use StringWriter and StringReader to treat textual information as a stream of in-memory characters. This can prove helpful when you wish to append character-based information to an underlying buffer. The following code sample illustrates this by writing a block of string data to a StringWriter object, rather than to a file on the local hard drive.

static void Main(string[] args)
{
    // writing
    using (StringWriter sw = new StringWriter())
    {
        sw.WriteLine("helloooooooooooooooooooo");

        // Reading
        using (StringReader sr = new StringReader(sw.ToString()))
        {
            string input = null;
            while ((input = sr.ReadLine()) != null)
            {
                Console.WriteLine(input);
            }
        }
    }
}

Summary

This article begins with an introduction to the .NET file system and its detailed class hierarchy. We have learned to manipulate a physical file or directory on your hard drive using the File and Directory classes. Next, we examined the Stream class in detail. The System.IO namespace provides numerous writer and reader types, for instance, FilStream, BinaryStream, StringStream, and so on.So, this article provides a full understanding to access data from a hard drive and write them back.


Similar Articles