Overview of File Processing

Introduction

When you are working in an application, you provide values and you issue commands to the computer. You can provide values by entering them in an application, such as a form. You issue commands such as asking the computer (or an application) to play music, to open a webpage, to send an email, etc. You also read values or text that the computer application presents to you. You can read text from a word processor or an electronic spreadsheet. You can view photos or videos from a family vacation or a company activity etc. File processing consists of storing values in the computer and retrieving those values when necessary.

Practical LearningPractical Learning: Introducing File Processing

A File

A piece of information used in an application is primarily represented as a group of bits. A file is a series of bits or bytes of data that are arranged in a particular manner in the computer memory. For easy storage, location, and management, the bytes are stored on a medium such as a hard drive, a solid state drive, or any valid and supported type of storage. When these bytes belong to a single but common entity and hold values that are stored on a medium, the group is referred to as a file.

A Document

Remember that a file, as an object, is used to store values in terms of bits and bytes. We will see the types of operations a user can perform on the file object. Perhaps the most regular operation a user performs in the computer is to open a file, such as a text file, to view its content, such as its text. When a user accesses or opens a file to view or use its content, the object that displays to the user is called a document.

A Directory, a Folder

For greater management, files can be created or stored in a parent object called a directory or a folder. Since a file is a unit of storage and it stores information, it has a size, which is the number of bits it uses to store its values.

A File Path

To manage it, a file has a location also called a path that specifies where and/or how the file can be retrieved.

The Attributes of a File

for better management, a file has some characteristics, referred to as attributes. Some attributes indicate what can be done on the file. Some other attribute provide specific information that the programmer or the operating system can use when dealing with the file.

The Name of a File

To create a file, a user must first decide where it would be located: this is a requirement. There are various means of creating files. When creating a file, the user must give it a name following the rules of the operating system combined with those of the file system. The most fundamental piece of information of a file must is a name.

Once a user has created a file, whether the file is empty or not, the operating system assigns basic pieces of information to it. Once a file is created, it can be opened, updated, modified, renamed, etc.

Streaming Prerequisites

A Streams

File processing consists of creating, storing, and/or retrieving the contents of a file from a recognizable medium. A stream is the technique or means of performing file processing. In order to manage files stored in a computer, each file must be able to provide basic pieces of information about itself. This basic information is specified when the file is created but can change during the lifetime of a file.

Introduction to Streaming

To support file processing, the .NET Framework provides a namespace named System.IO. That namespace contains many different classes to handle practically any type of file operation you may need to perform. Here is an example of including that namespace in a document:

using System.IO;

namespace Exercises
{
    public partial class Exercise : Form
    {
        public Exercise()
        {
            InitializeComponent();
        }
    }
}

In the .NET Framework, the parent class of file processing is named Stream. With the Stream class, you can store data to a stream or you can retrieve data from a stream. Stream is an abstract class. This means that you can declare a Stream variable but you cannot use it to initialize a variable for file processing. As an abstract class, Stream is used as the parent of the classes that actually implement the necessary operations. You will usually use a combination of classes to perform a typical operation. For example, some classes are used to create a stream object while some others are used to write data to the created stream.

The Name of a File

Before performing file processing, one of your early decisions will consist of specifying the type of operation you want the user to perform. For example, the user may want to create a brand new file, open an existing file, or perform a routine operation on a file. In all or most cases, whether you are creating a new file or manipulating an existing one, you must specify the name of the file. You can do this by declaring a string variable but, as we will learn later on, most classes used to create a stream can take a string that represents the file.

If you are creating a new file, there are certainly some rules you must observe. The name of a file follows the rules of the operating system.

The Extension of a File

To distinguish files, their names should end with a period and one or more characters and/or symbols. This last character or combination is referred to as the file extension. An application can be configured to support different types of files; that is, files with different extensions.

Based on this, if you declare a string variable to hold the name of the file, you can simply initialize the variable with the necessary name and its extension. Here is an example:

private void btnSave_Click(object sender, EventArgs e)
{
    string Filename = "Employees.spr";
}

The Path to a File

If you declare a string as above, the file will be created in the folder of the application. Otherwise, you can create your new file anywhere in the hard drive. To do that, you must provide a complete path where the file will reside. A path is a string that specifies the drive (such as A:, C:, or D:). The sections of a complete path string are separated by a backslash. For example, a path can be made of a folder followed by the name of the file. An example is:

C:\Palermo.tde 

A path can also consist of a drive followed by the name of the folder in which the file will be created. Here is an example:

C:\Program Files\Palermo.tde

A path can also indicate that the file will be created in a folder that itself is inside of another folder. In this case, remember that the names of folders and sub-folders must be separated by backslashes.

The backslash character is used to create or manage escape sequences and it can be included in a string value to make up an escape sequence. Because of this, every time you include a backslash in a string, the compiler thinks that you are trying to provide an escape sequence. In this case, if the combination of the backslash and the character that follows the backslash is not recognized as an escape sequence, you would get an error. To solve this problem, you have two options. To indicate that the backslash must be considered as a character in its own right, you can double it. Here are examples:

private void btnSave_Click(object sender, EventArgs e)
{
    string Filename = "C:\\Documents and Settings\\Employees.spr";
}

As an alternative, you can keep one backslash in each placeholder but precede the value of the string with the @ symbol. Here is an example:

private void btnSave_Click(object sender, EventArgs e)
{
    string Filename = @"C:\Documents and Settings\Employees.spr";
}

In the same way, you can declare a string variable to represent the name of an existing file that you plan to use in your program. You can also represent its path.

When providing a path to the file, if the drive you specify doesn't exist or cannot be read, the compiler would consider that the file doesn't exist. If you provide folders that don't exist in the drive, the compiler would consider that the file doesn't exist. This also means that the compiler will not create the folder(s) (the .NET Framework provides all means to create a folder but you must ask the compiler to create it; simply specifying a folder that doesn't exist will not automatically create it, even if you are creating a new file).

Introduction to Drives

Description

A drive is a physical device attached to a computer so it can store information. A drive can be a hard drive, a digital drive (CD ROM, DVD ROM), a flash (USB) drive, a memory card etc:

Hard Drive DVD Drive USB Flash Drive
Hard Drive DVD Drive USB Flash Drive
      
Floppy Drive Memory Card
Floppy Drive Flash Memory

A drive can reside inside a computer. That's the case for internal hard drives and most CD or DVD drives. A drive can also reside outside. That's the case for most flash (USB) drives. There are also versions of external hard drives and external DVD drives:

Hard Drive Floppy Drive USB Flash Drive
External Hard Drive External Floppy Drive USB Flash Drive Holder

A drive is referred to as virtual if it is not a real physical object.

While most drives are connected to a computer, a device connected to another computer can also be used as a drive. This is the case for network drives. The drive must be "shared" so that networked computers can access it.

Not all computers have the same drives and not all computers deal with the same means of storing data. Still, to simplify their identification, all objects used to hold data are referred to as drives. Because there are different ways to consider drives, there are also various means of accessing them.

There are two techniques of referring to drives. A drive that is directly connected to a computer, whether internally or externally, is referred to as a local drive. In Microsoft Windows, a local drive is represented by a letter, in uppercase, followed by a colon ":", and a backslash "\". If a hard disk is partitioned, each partition uses its own letter and is represented as its own drive.

Getting the List of Drives of a Computer

Normally, you will hardly be concerned with the creation of drives. The operating system "creates" or assigns a drive whenever it juges it necessary (of course, you can change the configuration of a drive such as its partitions, letter, etc). For example, as soon as you connect a USB drive to a port, the operating system automatically creates a drive and assigns a letter to it. You will only need to identify the drives that are available on a computer on which  your application is running. One of the primary operations you will perform consists of getting a list of drives on the computer.

The .NET Framework provides many classes that can assist you to identify the drives of a computer. The main class used to manage the drives of a computer is named DriveInfo.

We were already introduced to a class named Environment. This class is equipped with a method named GetLogicalDrives. Its syntax is:

public static string[] GetLogicalDrives()

When called, this method produces an array of strings where each element represents a logical drive in the computer. You can then use the drives as you see fit. Here is an example:

private void btnDrives_Click(object sender, EventArgs e)
{
    string[] strDrives = Environment.GetLogicalDrives();

    foreach (string strDrive in strDrives)
    {
        MessageBox.Show("Logical Drive: " + strDrive,
                        "Logical Drives",
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Information);
    }
}

Besides Environment, the .NET Framework provides a class named DriveInfo. Besides the Environment.GetLogicalDrives() method, the DriveInfo class is equipped with a method named GetDrives(). Its syntax is:

public static DriveInfo[] GetDrives();

This methodd provides its own means of getting a list of logical drives on the local computer. As opposed to a list of strings, the DriveInfo.GetDrives() method produces an array of DriveInfo objects, which is an array of logical drives on the computer. Here is an example of calling this method:

private void btnDrives_Click(object sender, EventArgs e)
{
    DriveInfo[] diLocalDrives = DriveInfo.GetDrives();
}

Characteristics of Drives

Introduction

In microsoft Windows, a local drive is represented by a letter followed by :\. For example, in most personal computers, the (main) hard drive is represented as C:\.

If you know the drive you want to use or access, the DriveInfo class provides a constructor that allows you to get a reference to that drive. This is the only constructor of this class. The syntax of the constructor is:

public DriveInfo(string driveName);

If you want to access a drive, you can declare a DriveInfo variable and pass the drive letter to this constructor. Here is an example:

private void btnDrives_Click(object sender, EventArgs e)
{
    DriveInfo diHardDrive = new DriveInfo(@"C:\");
}

The Name of a Drive

If you want to get the name of a drive, you can access the Name property of the DriveInfo class:

public string Name { get; }

Here is an example:

private void btnDrives_Click(object sender, EventArgs e)
{
    DriveInfo[] diLocalDrives = DriveInfo.GetDrives();

    foreach (DriveInfo diLogicalDrive in diLocalDrives)
    {
        MessageBox.Show("Logical Drive: " + diLogicalDrive.Name,
                        "Logical Drives",
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Information);
    }
}

The Type of a Drive

A drive is primarily recognized by its category. Examples of categories are hard drives, optical drives (CD, DVD, BluRay drives), etc. The categories of drives are stored in a property named DriveType of the DriveInfo class. The DriveType property is based on an enumeration of the same name:

public DriveType DriveType { get; }

Its members are:

Member Description
Unknown The drive is unrecognizable
NoRootDirectory The root of the drive is unrecognizable
Removable This can be a floppy drive, a USB drive, a memory card, etc. A drive that can be removed at will
Fixed This is a hard drive or a partition on an HD
Network This is a network drive, usually located on another computer
CDROM This is drive CD or DVD drive
Ram This is the random access memory

The Type of Format

The format system is the scheme that a computer (actually the operating system) uses to store and process the values in its drives. Microsoft Windows uses various types of formats, including FAT32 and NTFS. To let you know the format scheme that a drive is using, the DriveInfo class is equipped with a property named DriveFormat:

public string DriveFormat { get; }

Here is an example of accessing this property:

private void btnDrives_Click(object sender, EventArgs e)
{
    DriveInfo diHardDrive = new DriveInfo(@"C:\");

    if( diHardDrive != null )
    {
        MessageBox.Show("Operating System:  " + 
                        Environment.OSVersion.ToString() + Environment.NewLine +
                        "Drive Format:      " + diHardDrive.DriveFormat,
                        "Exercise",
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Information);
    }
}

The Capacity of a Drive

A drive is priarily used to hold some values. The capacity of a drive is the amount of data it can hold. This is usually measured in bits and bytes. As there are various types of drives, they also have different capacities. To help you to know the capacity of a drive, the DriveInfo class is equipped with a property named TotalSize that is of type long:

public long TotalSize { get; }

This property produces a long integer that represents the normal total capacity of a drive. Here is an example of accessing it:

private void btnDrives_Click(object sender, EventArgs e)
{
    DriveInfo diHardDrive = new DriveInfo(@"C:\");

    if( diHardDrive != null )
    {
        MessageBox.Show("You hard drive has a capacity of " +
                        diHardDrive.TotalSize.ToString("N") + " bytes.",
                        "Logical Drives",
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Information);
    }
}

As values are stored in a drive, a drive keeps filled up. In some drives, values can be deleted, copied, or moved. This means that the capacity of some drives changes some time to time. At one time, to know the available free space of a drive, you can get the value of the AvailableFreeSpace property of its DriveInfo object:

public long AvailableFreeSpace { get; }

Here is an example of accessing this property:

private void btnDrives_Click(object sender, EventArgs e)
{
    DriveInfo diHardDrive = new DriveInfo(@"C:\");

    if( diHardDrive != null )
    {
        MessageBox.Show("Hard Drive Capacity:  " +
                        diHardDrive.TotalSize.ToString() + " bytes.\n" +
                        "Available Free Space: " +
                        diHardDrive.AvailableFreeSpace.ToString() + " bytes.\n",
                        "Exercise",
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Information);
    }
}

Directories

Introduction

A directory is a section of a medium (floppy disc, flash drive, hard drive, CD, DVD, BD, etc) used to delimit a group of files. There are many fundamental differences between a diretory and a file:

The similarities of both types are:

Directory Creation

Before using a directory, you must first have it. You can use an existing directory if the operating system or someone else had already created one. You can also create a new directory. Directories are created and managed by various classes but the .NET Framework provides a class named Directory. This is the fundamental class to deal with directories. Directory is a static class. All of its methods are static, which means you will never need to declare an instance of the Directory class in order to use it.

Besides the Directory class, the .NET Framework provides a class named DirectoryInfo. This call supports additional operations on folders and sub-folders.

To let you create a directory, the Directory class iequipped with an overloaded method named CreateDirectory. This method is available in two versions. One of the versions uses the following syntax:

public static DirectoryInfo CreateDirectry(string path);

This method takes as argument the (complete) path of the desired directory. Here is an example:

E:\Programs\Business Orders\Customer Information

When this method is called:

  1. It first checks the parent drive, in this case E:\.
    If the drive doesn't exist, because this method cannot create a drive, the compiler would throw a DirectoryNotFoundException exception
  2. If the drive (in this case E:\) exists, the compiler moves to the first directory part of the path; in this case this would be the Programs folder in the E:\ drive.
    If the folder doesn't exist, the compiler would create it. If that first directory doesn't exist, this means that the other directory(or directories), if any, under the first don't exist. So, the compiler would create it/them
  3. If the first directory exists and if there is no other directory under that directory, the compiler would stop and would not do anything further
  4. If the directory exists and there is a sub-directory specified under it, the compiler would check the existence of that directory.
    If the sub-directory exists, the compiler would not do anything further and would stop.
    If the sub-directory doesn't exist, the compiler would create it
  5. The compiler would repeat step d until the end of the specified path

The Directory.CreateDirectory() method returns a DirectoryInfo object that you can use as you see fit. Here is an example of calling this method:

namespace Exercises
{
    public partial class Exercise : Form
    {
        public Exercise()
        {
            InitializeComponent();

            /* If you want to use a drive other than the C:> drive, 
             * change the letter in the following line. */
            Directory.CreateDirectory(@"C:\Gas Utility Company");
        }
    }
}

Checking for a Directory Existence

Before using or creating a directory, you can first check if it exists. This is because, if a directory already exists in the location where you want to create it, you would be prevented from creating one with the same name. In the same way, if you just decide to directly use a directory that doesn't exist, the operation you want to perform may fail because the directory would not be found.

To let you check whether a directory exists or not, the Directory class includes a Boolean static method named Exists. Its syntax is:

public static bool Exists(String path);

This method receives the (complete) path of the directory. If the path exists, the method returns true. If the directory doesn't exist, the method returns false.

Deleting a Directory

To let you get rid of a directory, the Directory class provides a method named Delete. The Directory.Delete() method is overloaded with two versions. One of the versions uses the following syntax;

public static void Delete(string path);

When calling this method, pass the complete path as argument. The other version uses the following syntax:

public static void Delete(string path, bool recursive);

This time, the second argument allows you to specify whether you want the sub-folders and their contents to be deleted also.

Listing the Files of a Directory

One of the most routine operations performed in a directory consists of looking for a file. Microsoft Windows operating systems and the user's intuition have different ways of addressing this issue. The .NET Framework also provides its own means of performing this operation, through various techniques. You can start by checking the sub-directories and files inside of a main directory.

To let you look for files in a directory, the DirectoryInfo class is equipped with a method named GetFiles, which is overloaded with three versions.

The .NET Framework Support for Files

Introduction

The primary support of a file as an object is provided by a .NET Framework class called File. This static class is equipped with various types of (static) methods to create, save, open, copy, move, delete, or check the existence of a file.

File Existence

One of the valuable operations that the File class can perform is to check the existence of the file you want to use. For example, if you are creating a new file, you may want to make sure it doesn't exist already because if you try to create a file that exists already, the compiler may first delete the old file before creating the new one. This could lead to unpredictable results, especially because such a file is not sent to the Recycle Bin. On the other hand, if you are trying to open a file, you should first make sure the file exists, otherwise the compiler will not be able to open a file it cannot find.

To let you check the existence of a file, the File class is equipped with a method named Exists. Its syntax is:

public static bool Exists(string path);

If you provide only the name of the file, the compiler would check it in the folder of the application. If you provide the path to the file, the compiler would check its drive, its folder(s) and the file itself. In both cases, if the file exists, the method returns true. If the compiler cannot find the file, the method returns false. It's important to know that if you provided a complete path to the file, any slight mistake may produce a bad result.

File Creation

Besides checking the existence of the file, the File class can be used to create a new file. To support this operation, the File class is equipped with a method named Create. This meathod is overloaded with two versions as follows:

public static FileStream Create(string path);
public static FileStream Create(string path, int buffersize);

In both cases, the File.Create() method returns a Stream value, in this case an object of a class named FileStream. As the File.Create() method indicates, it takes the name or path of the file as argument. If you know or want to specify the size, in bytes, of the file, you can use the second version.

To provide the same operation of creating a file, the File class provides a method named Open. It is overloaded in three versions as follows:

public static FileStream Open(string path, FileMode mode);
public static FileStream Open(string path, 
                            FileMode mode, 
		                    FileAccess access);
public static FileStream Open(string  path,
                              FileMode mode,
                              FileAccess access,
                              FileShare share);

Access to a File

In order to perform an operation on a file, you must specify to the operating system how to proceed. One of the options you have is to indicate the type of access that will be granted on the file. This access is specified using an enumeration named FileAccess. The members of the FileAccess enumeration are:

File Sharing

In standalone workstations, one person is usually able to access and open a file then perform the necessary operation(s) on it. In networked computers, you may create a file that different people can access at the same time or you may cause one file to access another file to retrieve information. One file may depend on another. Based on this, when an operation must be performed on a file, you may have to specify how a file can be shared. This is done through an enumeration named FileShare.

The values of the FileShare enumeration are:

The Mode of a File

Besides the access to a file, another option you will most likely specify to the operating system is referred to as the mode of a file. It is specified through an enumeration named FileMode. The members of the FileMode enumeration are:

Fundamentals of File Streaming

Introduction

File streaming consists of performing one of the routine operations on a file, such as creating or opening it. This basic operation can be performed using a class called FileStream. You can use a FileStream object to get a stream ready for processing. As one of the most complete classes of file processing of the .NET Framework, FileStream is equipped with all necessary properties and methods. To use it, you must first declare a variable of it. The class is equipped with nine constructors.

One of the constructors (the second) of the FileStream class has the following syntax:

public FileStream(string path, FileMode mode);

This constructor takes as its first argument the name of the file or its path. The second argument specifies the type of operation to perform on the file. Here is an example:

private void btnSave_Click(object sender, EventArgs e)
{
        string Filename = "Employees.spr";

        FileStream fstPersons = new FileStream(Filename,
                                                FileMode.Create);
}

Stream Writing

A streaming operation is typically used to create a stream. Once the stream is ready, you can write data to it. The writing operation is performed through various classes. One of these classes is named BinaryWriter.

The BinaryWriter class can be used to write values of primitive data types (char, int, float, double, etc). To use a BinaryWriter value, you can first declare its variable. To do this, you would use one of the class' three constructors. The first constructor is the default, meaning it doesn't take an argument. The second constructor has the following syntax:

public BinaryWriter(Stream output);

This constructor takes as argument a Stream value, which could be a FileStream variable. Here is an example:

private void btnSave_Click(object sender, EventArgs e)
{
    string Filename = "Employees.spr";

    FileStream fstPersons = new FileStream(Filename,
                                           FileMode.Create);
    BinaryWriter wrtPersons = new BinaryWriter(fstPersons);
}

Most classes that are used to add values to a stream are equipped with a method called Write. This is also the case for the BinaryWriter class. This method takes as argument the value that must be written to the stream. The method is overloaded so that there is a version for each primitive data type. Here is an example that adds strings to a newly created file:

Persons

private void btnSave_Click(object sender, EventArgs e)
{
    string Filename = "Employees.spr";

    FileStream fstPersons = new FileStream(Filename,
                                           FileMode.Create);
    BinaryWriter wrtPersons = new BinaryWriter(fstPersons);
    
    wrtPersons.Write(txtPerson1.Text);
    wrtPersons.Write(txtPerson2.Text);
    wrtPersons.Write(txtPerson3.Text);
    wrtPersons.Write(txtPerson4.Text);

    txtPerson1.Text = "";
    txtPerson2.Text = "";
    txtPerson3.Text = "";
    txtPerson4.Text = "";
}

Stream Closing

When you use a stream, it requests resources from the operating system and uses them while the stream is available. When you are not using the stream anymore, you should free the resources and make them available again to the operating system so that other services can use them. This is done by closing the stream.

To let you close a stream, the classes used for streaming (reading or writing) are equipped with a method named Close. Here are examples of calling this method:

private void btnSave_Click(object sender, EventArgs e)
{
    string Filename = "Employees.spr";

    FileStream fstPersons = new FileStream(Filename,
                FileMode.Create);
    BinaryWriter wrtPersons = new BinaryWriter(fstPersons);
    
    wrtPersons.Write(txtPerson1.Text);
    wrtPersons.Write(txtPerson2.Text);
    wrtPersons.Write(txtPerson3.Text);
    wrtPersons.Write(txtPerson4.Text);

    txtPerson1.Text = "";
    txtPerson2.Text = "";
    txtPerson3.Text = "";
    txtPerson4.Text = "";

    wrtPersons.Close();
    fstPersons.Close();
}

Stream Reading

As opposed to writing to a stream, you may want to read existing data from it. Before doing this, you can first specify your intent to the streaming class using the FileMode enumeration. This can be done using the FileStream class as follows:

private void btnOpen_Click(object sender, EventArgs e)
{
    string Filename = "Employees.spr";
    FileStream fstPersons = new FileStream(Filename, FileMode.Open);
}

Once the stream is ready, you can get prepared to read data from it. To support this, the .NET Framework provides a class named BinaryReader. This class provides two constructors. One of the constructors (the first) has the following syntax:

public BinaryReader(Stream input);

This constructor takes as argument a Stream value, which could be a FileStream object. After declaring a FileStream variable using this constructor, you can read data from it. To support this, the class provides an appropriate method for each primitive data type.

After using the stream, you should close it to reclaim the resources it was using. As mentioned previously, this is done by calling the Close() method of the streaming class.

Here is an example of using the mentioned methods:

private void btnOpen_Click(object sender, EventArgs e)
{
    string Filename = "Employees.spr";
    FileStream fstPersons = new FileStream(Filename, FileMode.Open);
    BinaryReader rdrPersons = new BinaryReader(fstPersons);

    txtPerson1.Text = rdrPersons.ReadString();
    txtPerson2.Text = rdrPersons.ReadString();
    txtPerson3.Text = rdrPersons.ReadString();
    txtPerson4.Text = rdrPersons.ReadString();

    rdrPersons.Close();
    fstPersons.Close();
}

Practical LearningPractical Learning: Ending the Lesson


Previous Copyright © 2008-2024, FunctionX Friday 10 June 2022 Next