+ All Categories
Home > Documents > Unit 5: Understanding .NET Assemblies & Libaries · Unit 5: Understanding .NET Assemblies &...

Unit 5: Understanding .NET Assemblies & Libaries · Unit 5: Understanding .NET Assemblies &...

Date post: 02-Aug-2020
Category:
Upload: others
View: 7 times
Download: 0 times
Share this document with a friend
22
Unit 5: Understanding .NET Assemblies & Libraries 1 Prof. Sushant S Sundikar C# .Net Programming Unit V: Understanding .NET Assemblies & Libraries The Role of .NET Assemblies, o Understanding the format of .NET Assemblies o Building and Consuming a Single- File Assembly o Building and Consuming a Multi-File Assembly o Shared Assemblies The System IO Namespace o Directory (Info) and File (Info) types, o Working with DirectoryInfo, Directory, FileInfo, File Classes Abstract Stream Class, o StreamWriters and StreamReaders o StringWriters and StringReaders o BinaryWriters and BinaryReaders o Programmatically watching files .NET applications are constructed by piecing together any number of assemblies. Simply put, an assembly is a versioned, self-describing binary file hosted by the CLR. .NET assemblies have *.exe or *.dll file extensions. Here are some of the benefits provided by the assembly. Assemblies Promote Code Reuse A code library (also termed a class library) is a *.dll that contains types (classes, interfaces, namespaces) intended to be used by external applications. The .NET platform allows you to reuse types in a language-independent manner. For example, you could create a code library in C# and reuse that library in any other .NET programming language. It is possible to not only allocate types (classes, interfaces, and namespaces) across languages, but derive from them as well. A base class defined in C# could be extended by a class authored in Visual Basic .NET. The point is that when you begin to break apart a single executable file into numerous .NET assemblies, you achieve a language- neutral form of code reuse. Assemblies Establish a Type Boundary The assembly in which a type resides establishes a type’s identity. For example, if you have two uniquely named assemblies (say, MyCars.dll and YourCars.dll) that both define a namespace (CarLibrary) containing a class named SportsCar, they are considered unique types in the .NET universe. Assemblies Are Versionable Units .NET assemblies are assigned a four-part numerical version number of the form <major>.<minor>.<build>.<revision> (if you do not explicitly provide a version number using the [AssemblyVersion] attribute, the assembly is automatically assigned a version of 0.0.0.0). This number, in conjunction with an optional public key value, allows multiple versions of the same assembly to coexist in harmony on a single machine.
Transcript
Page 1: Unit 5: Understanding .NET Assemblies & Libaries · Unit 5: Understanding .NET Assemblies & Libraries 4 Prof. Sushant S Sundikar C# .Net Programming A multifile assembly, on the other

Unit 5: Understanding .NET Assemblies & Libraries 1

Prof. Sushant S Sundikar C# .Net Programming

Unit V: Understanding .NET Assemblies & Libraries

• The Role of .NET Assemblies,

o Understanding the format of .NET Assemblies

o Building and Consuming a Single- File Assembly

o Building and Consuming a Multi-File Assembly

o Shared Assemblies

• The System IO Namespace

o Directory (Info) and File (Info) types,

o Working with DirectoryInfo, Directory, FileInfo, File Classes

• Abstract Stream Class,

o StreamWriters and StreamReaders

o StringWriters and StringReaders

o BinaryWriters and BinaryReaders

o Programmatically watching files

.NET applications are constructed by piecing together any number of assemblies. Simply put, an

assembly is a versioned, self-describing binary file hosted by the CLR. .NET assemblies have *.exe or

*.dll file extensions. Here are some of the benefits provided by the assembly.

Assemblies Promote Code Reuse

A code library (also termed a class library) is a *.dll that contains types (classes, interfaces,

namespaces) intended to be used by external applications. The .NET platform allows you to reuse

types in a language-independent manner. For example, you could create a code library in C# and

reuse that library in any other .NET programming language. It is possible to not only allocate types

(classes, interfaces, and namespaces) across languages, but derive from them as well. A base class

defined in C# could be extended by a class authored in Visual Basic .NET. The point is that when you

begin to break apart a single executable file into numerous .NET assemblies, you achieve a language-

neutral form of code reuse.

Assemblies Establish a Type Boundary

The assembly in which a type resides establishes a type’s identity. For example, if you have two

uniquely named assemblies (say, MyCars.dll and YourCars.dll) that both define a namespace

(CarLibrary) containing a class named SportsCar, they are considered unique types in the .NET

universe.

Assemblies Are Versionable Units

.NET assemblies are assigned a four-part numerical version number of the form

<major>.<minor>.<build>.<revision> (if you do not explicitly provide a version number using the

[AssemblyVersion] attribute, the assembly is automatically assigned a version of 0.0.0.0). This

number, in conjunction with an optional public key value, allows multiple versions of the same

assembly to coexist in harmony on a single machine.

Page 2: Unit 5: Understanding .NET Assemblies & Libaries · Unit 5: Understanding .NET Assemblies & Libraries 4 Prof. Sushant S Sundikar C# .Net Programming A multifile assembly, on the other

Unit 5: Understanding .NET Assemblies & Libraries 2

Prof. Sushant S Sundikar C# .Net Programming

Assemblies Are Self-Describing

Assemblies are regarded as self-describing in part because they record every external assembly it

must have access to in order to function correctly. Thus, if your assembly requires

System.Windows.Forms.dll and System.Drawing.dll, they will be documented in the assembly’s

manifest.

In addition to manifest data, an assembly contains metadata that describes the composition

(member names, implemented interfaces, base classes, constructors and so forth) of every

contained type. Given that an assembly is documented in such vivid detail, the CLR does not consult

the Win32 system registry to resolve its location.

Assemblies Are Configurable

Assemblies can be deployed as “private” or “shared.” Private assemblies reside in the same directory

(or possibly a subdirectory) as the client application making use of them. Shared assemblies, on the

other hand, are libraries intended to be consumed by numerous applications on a single machine

and are deployed to a specific directory termed the Global Assembly Cache (GAC).

Regardless of how you deploy your assemblies, you are free to author XML-based configuration files.

Using these configuration files, the CLR can be instructed to “probe” for assemblies under a specific

location, load a specific version of a referenced assembly for a particular client, or consult an

arbitrary directory on your local machine, your network location, or a web-based URL.

Understanding the Format of a .NET Assembly

A .NET assembly (*.dll or *.exe) consists of the following elements:

• A Win32 file header

• A CLR file header

• CIL code

• Type metadata

• An assembly manifest

• Optional embedded resources

The Win32 File Header

The Win32 file header establishes the fact that the assembly can be loaded and manipulated by the

Windows family of operating systems. This header data also identifies the kind of application

(consolebased, GUI-based, or *.dll code library) to be hosted by the Windows operating system.

The CLR File Header

The CLR header is a block of data that all .NET files must support in order to be hosted by the CLR. In

a nutshell, this header defines numerous flags that enable the runtime to understand the layout of

the managed file. For example, flags exist that identify the location of the metadata and resources

within the file, the version of the runtime the assembly was built against, the value of the (optional)

public key, and so forth.

Page 3: Unit 5: Understanding .NET Assemblies & Libaries · Unit 5: Understanding .NET Assemblies & Libraries 4 Prof. Sushant S Sundikar C# .Net Programming A multifile assembly, on the other

Unit 5: Understanding .NET Assemblies & Libraries 3

Prof. Sushant S Sundikar C# .Net Programming

CIL Code, Type Metadata, and the Assembly Manifest

At its core, an assembly contains CIL code, which as you recall is a platform- and CPU-agnostic

intermediate language. At runtime, the internal CIL is compiled on the fly (using a just-in-time [JIT]

compiler) to platform- and CPU-specific instructions.

An assembly also contains metadata that completely describes the format of the contained types as

well as the format of external types referenced by this assembly. The .NET runtime uses this

metadata to resolve the location of types (and their members) within the binary, lay out types in

memory, and facilitate remote method invocations.

An assembly must also contain an associated manifest (also referred to as assembly metadata).The

manifest documents each module within the assembly, establishes the version of the assembly, and

also documents any external assemblies referenced by the current assembly.

Optional Assembly Resources

Finally, a .NET assembly may contain any number of embedded resources such as application icons,

image files, sound clips, or string tables.

Single-File and Multifile Assemblies

Technically speaking, an assembly can be composed of multiple modules. A module is really nothing

more than a generic term for a valid .NET binary file. In most situations, an assembly is in fact

composed of a single module. In this case, there is a one-to-one correspondence between the

(logical) assembly and the underlying (physical) binary (hence the term single-file assembly).

Single-file assemblies contain all of the necessary elements (header information, CIL code, type

metadata, manifest, and required resources) in a single *.exe or *.dll package. Figure 5-1 illustrates

the composition of a single-file assembly.

Figure 5-1: A single-file assembly

Page 4: Unit 5: Understanding .NET Assemblies & Libaries · Unit 5: Understanding .NET Assemblies & Libraries 4 Prof. Sushant S Sundikar C# .Net Programming A multifile assembly, on the other

Unit 5: Understanding .NET Assemblies & Libraries 4

Prof. Sushant S Sundikar C# .Net Programming

A multifile assembly, on the other hand, is a set of .NET *.dlls that are deployed and versionedas a

single logic unit. Formally speaking, one of these *.dlls is termed the primary module and contains

the assembly-level manifest (as well as any necessary CIL code, metadata, header information, and

optional resources). The manifest of the primary module records each of the related *.dll files it is

dependent upon.

As a naming convention, the secondary modules in a multifile assembly take a *.netmodule file

extension; however, this is not a requirement of the CLR. Secondary *.netmodules also contain CIL

code and type metadata, as well as a module-level manifest, which simply records the externally

required assemblies of that specific module.

The major benefit of constructing multifile assemblies is that they provide a very efficient way to

download content. For example, assume you have a machine that is referencing a remote multifile

assembly composed of three modules, where the primary module is installed on the client. If the

client requires a type within a secondary remote *.netmodule, the CLR will download the binary to

the local machine on demand to a specific location termed the download cache.

Another benefit of multifile assemblies is that they enable modules to be authored using multiple

.NET programming languages Once each of the individual modules has been compiled, the modules

can be logically “connected” into a logical assembly using tools such as the assembly linker (al.exe).

Figure 11-4 illustrates a multifile assembly composed of three modules, each authored using a

unique .NET programming language.

Figure 5-2. The primary module records secondary modules in the assembly manifest

Page 5: Unit 5: Understanding .NET Assemblies & Libaries · Unit 5: Understanding .NET Assemblies & Libraries 4 Prof. Sushant S Sundikar C# .Net Programming A multifile assembly, on the other

Unit 5: Understanding .NET Assemblies & Libraries 5

Prof. Sushant S Sundikar C# .Net Programming

Exploring the System.IO Namespace

The System.IO namespace is the region of the base class libraries devoted to file-based (and

memory-based) input and output (I/O) services. Like any namespace, System.IO defines a set of

classes, interfaces, enumerations, structures, and delegates, which focus on the programmatic

manipulation of physical directories and files.

Key Members of the System.IO Namespace

Nonabstract I/O Class Type Meaning in Life

BinaryReader These types allow you to store and retrieve primitive data types

BinaryWriter (integers, Booleans, strings, and whatnot) as a binary value.

BufferedStream This type provides temporary storage for a stream of bytes that may be

committed to storage at a later time.

Directory These types are used to manipulate a machine’s directory

DirectoryInfo structure. The Directory type exposes functionality primarily as static methods. The

DirectoryInfo type exposes similar functionality from a valid object

variable.

DriveInfo This type (new to .NET 2.0) provides detailed information regarding the

drives on a given machine.

File

FileInfo

These types are used to manipulate a machine’s set of files. The File type

exposes functionality primarily as static methods. The FileInfo type

exposes similar functionality from a valid object variable.

FileStream This type allows for random file access (e.g., seeking capabilities) with

data represented as a stream of bytes.

FileSystemWatcher This type allows you to monitor the modification of a given external file.

MemoryStream This type provides random access to streamed data stored in memory

rather than a physical file.

Path This type performs operations on System.String types that contain file or

directory path information in a platform-neutral manner.

StreamWriter

StreamReader

These types are used to store (and retrieve) textual information to (or

from) a file. These types do not support random file access.

StringWriter

StringReader

Like the StreamReader/StreamWriter types, these classes also work with

textual information. However, the underlying storage is a string buffer

rather than a physical file.

Page 6: Unit 5: Understanding .NET Assemblies & Libaries · Unit 5: Understanding .NET Assemblies & Libraries 4 Prof. Sushant S Sundikar C# .Net Programming A multifile assembly, on the other

Unit 5: Understanding .NET Assemblies & Libraries 6

Prof. Sushant S Sundikar C# .Net Programming

The Directory(Info) and File(Info) Types

System.IO provides four classes that allow you to manipulate individual files, as well as interact with

a machine’s directory structure. The first two classes, Directory and File, expose creation, deletion,

copying, and moving operations using various static members. The closely related FileInfo and

DirectoryInfo classes expose similar functionality as instance-level methods. In Figure 5-1, notice

that the Directory and File types directly extend System.Object, while DirectoryInfo and FileInfo

derive from the abstract FileSystemInfo type.

Figure 5-1 : The File- and Directory-centric types

The Abstract FileSystemInfo Base Class

The DirectoryInfo and FileInfo types receive many behaviors from the abstract FileSystemInfo base

class.

Table 5-2. FileSystemInfo Properties

Property Meaning in Life

Attributes Gets or sets the attributes associated with the current file that are

represented by the FileAttributes enumeration.

CreationTime Gets or sets the time of creation for the current file or directory.

Exists Can be used to determine if a given file or directory exists.

Extension Retrieves a file’s extension.

FullName Gets the full path of the directory or file.

LastAccessTime Gets or sets the time the current file or directory was last accessed.

LastWriteTime Gets or sets the time when the current file or directory was last written

to.

Name For files, gets the name of the file. For directories, gets the name of the

last directory in the hierarchy if a hierarchy exists. Otherwise, the Name

Page 7: Unit 5: Understanding .NET Assemblies & Libaries · Unit 5: Understanding .NET Assemblies & Libraries 4 Prof. Sushant S Sundikar C# .Net Programming A multifile assembly, on the other

Unit 5: Understanding .NET Assemblies & Libraries 7

Prof. Sushant S Sundikar C# .Net Programming

property gets the name of the directory.

Working with the DirectoryInfo Type

DirectoryInfo class contains a set of members used for creating, moving, deleting, and enumerating

over directories and subdirectories. In addition to the functionality provided by its base class

(FileSystemInfo), DirectoryInfo offers the key members in Table 5-3.

Table 16-3. Key Members of the DirectoryInfo Type

Members Meaning in Life

Create()

CreateSubdirectory()

Create a directory (or set of subdirectories), given a path name

Delete() Deletes a directory and all its contents

GetDirectories() Returns an array of strings that represent all subdirectories in the current

directory

GetFiles() Retrieves an array of FileInfo types that represent a set of files in the given

directory

MoveTo() Moves a directory and its contents to a new path

Parent Retrieves the parent directory of the specified path

Root Gets the root portion of a path

You begin working with the DirectoryInfo type by specifying a particular directory path as a

constructor parameter. If you want to obtain access to the current application directory (i.e., the

directory of the executing application), use the "." notation. Here are some examples:

// Bind to the current application directory.

DirectoryInfo dir1 = new DirectoryInfo(".");

// Bind to C:\Windows,using a verbatim string.

DirectoryInfo dir2 = new DirectoryInfo(@"C:\Windows");

In the second example, you are making the assumption that the path passed into the constructor

(C:\Windows) already exists on the physical machine. However, if you attempt to interact with a

nonexistent directory, a System.IO.DirectoryNotFoundException is thrown. Thus, if you specify a

directory that is not yet created, you will need to call the Create() method before proceeding:

// Bind to a nonexistent directory, then create it.

DirectoryInfo dir3 = new DirectoryInfo(@"C:\Windows\Testing");

dir3.Create();

Program ch05pg05.cs : Program to demonstrate the use of DirectoryInfo Class

Page 8: Unit 5: Understanding .NET Assemblies & Libaries · Unit 5: Understanding .NET Assemblies & Libraries 4 Prof. Sushant S Sundikar C# .Net Programming A multifile assembly, on the other

Unit 5: Understanding .NET Assemblies & Libraries 8

Prof. Sushant S Sundikar C# .Net Programming

class ch05pg05

{

static void Main(string[] args)

{

Console.WriteLine("***** Fun with Directory(Info) *****\n");

DirectoryInfo dir = new DirectoryInfo(@"C:\Windows");

// Dump directory information.

Console.WriteLine("***** Directory Info *****");

Console.WriteLine("FullName: {0} ", dir.FullName);

Console.WriteLine("Name: {0} ", dir.Name);

Console.WriteLine("Parent: {0} ", dir.Parent);

Console.WriteLine("Creation: {0} ", dir.CreationTime);

Console.WriteLine("Attributes: {0} ", dir.Attributes);

Console.WriteLine("Root: {0} ", dir.Root);

Console.WriteLine("**************************\n");

}

}

The FileAttributes Enumeration

The Attributes property exposed by FileSystemInfo provides various traits for the current directory

or file, all of which are represented by the FileAttributes enumeration (enum).

public enum FileAttributes

{

ReadOnly, Hidden,

// The file is part of the operating system or is used exclusively

by the operating system

System, Directory, Archive,

// This name is reserved for future use.

Device,

// The file is 'normal' as it has no other attributes set.

Normal, Temporary,

// Sparse files are typically large files whose data are mostly

zeros.

SparseFile,

Page 9: Unit 5: Understanding .NET Assemblies & Libaries · Unit 5: Understanding .NET Assemblies & Libraries 4 Prof. Sushant S Sundikar C# .Net Programming A multifile assembly, on the other

Unit 5: Understanding .NET Assemblies & Libraries 9

Prof. Sushant S Sundikar C# .Net Programming

// A block of user-defined data associated with a file or a

directory

ReparsePoint, Compressed, Offline,

// The file will not be indexed by the operating system's content

indexing service.

NotContentIndexed, Encrypted

}

Program ch05pg06.cs : Program to demonstrate the attribute enumeration in DirectoryInfo class

class ch05pg06

{

static void Main(string[] args)

{

Console.WriteLine("***** Fun with Directory(Info) *****\n");

DirectoryInfo dir = new DirectoryInfo(@"C:\Windows");

// Get all files with a *.bmp extension.

FileInfo[] bitmapFiles = dir.GetFiles("*.bmp");

// How many were found?

Console.WriteLine("Found {0} *.bmp files\n",

bitmapFiles.Length);

// Now print out info for each file.

foreach (FileInfo f in bitmapFiles)

{

Console.WriteLine("***************************\n");

Console.WriteLine("File name: {0} ", f.Name);

Console.WriteLine("File size: {0} ", f.Length);

Console.WriteLine("Creation: {0} ", f.CreationTime);

Console.WriteLine("Attributes: {0} ", f.Attributes);

Console.WriteLine("***************************\n");

}

}

}

Page 10: Unit 5: Understanding .NET Assemblies & Libaries · Unit 5: Understanding .NET Assemblies & Libraries 4 Prof. Sushant S Sundikar C# .Net Programming A multifile assembly, on the other

Unit 5: Understanding .NET Assemblies & Libraries 10

Prof. Sushant S Sundikar C# .Net Programming

Creating Subdirectories with the DirectoryInfo Type

You can programmatically extend a directory structure using the DirectoryInfo.CreateSubdirectory()

method. This method can create a single subdirectory, as well as multiple nested subdirectories, in a

single function call.

Example Program: ch05pg07.cs :- Program to demonstrate creation of sub directories.

class ch05pg07

{

static void Main(string[] args)

{

Console.WriteLine("***** Fun with Directory(Info) *****\n");

DirectoryInfo dir = new DirectoryInfo(@"C:\MyDirectory");

dir.Create();

// Create \MyFoo off initial directory.

dir.CreateSubdirectory("MyFoo");

// Create \MyBar\MyQaaz off initial directory.

dir.CreateSubdirectory(@"MyBar\MyQaaz");

}

}

Working with the Directory Type

Exposes static methods for creating, moving, and enumerating through directories and

subdirectories. This class cannot be inherited. Use the Directory class for typical operations such as

copying, moving, renaming, creating, and deleting directories. You can also use the Directory class to

get and set DateTime information related to the creation, access, and writing of a directory.

Because all Directory methods are static, it might be more efficient to use a Directory method rather

than a corresponding DirectoryInfo instance method if you want to perform only one action. Most

Directory methods require the path to the directory that you are manipulating.

Program ch05pg08.cs : The following example demonstrates how to move a directory and all its files

to a new directory. The original directory no longer exists after it has been moved.

using System;

using System.IO;

namespace ConsoleApplication

{

Page 11: Unit 5: Understanding .NET Assemblies & Libaries · Unit 5: Understanding .NET Assemblies & Libraries 4 Prof. Sushant S Sundikar C# .Net Programming A multifile assembly, on the other

Unit 5: Understanding .NET Assemblies & Libraries 11

Prof. Sushant S Sundikar C# .Net Programming

class Program

{

static void Main(string[] args)

{

string sourceDirectory = @"C:\source";

string destinationDirectory = @"C:\destination";

try

{

Directory.Move(sourceDirectory,

destinationDirectory);

}

catch (Exception e)

{

Console.WriteLine(e.Message);

}

}

}

}

Working with the FileInfo Class

The FileInfo class allows you to obtain details regarding existing files on your hard drive (time

created, size, file attributes, and so forth) and helps in the creation, copying, moving, and

destruction of files. In addition to the set of functionality inherited by FileSystemInfo are some core

members unique to the FileInfo class, are described in Table 5-3.

Member Meaning in Life

AppendText() Creates a StreamWriter type (described later) that appends text to a file

CopyTo() Copies an existing file to a new file

Create() Creates a new file and returns a FileStream type (described later) to interact

with the newly created file

CreateText() Creates a StreamWriter type that writes a new text file

Delete() Deletes the file to which a FileInfo instance is bound

Directory Gets an instance of the parent directory

DirectoryName Gets the full path to the parent directory

Length Gets the size of the current file or directory

MoveTo() Moves a specified file to a new location, providing the option to specify a new

filename

Name Gets the name of the file

Open() Opens a file with various read/write and sharing privileges

Page 12: Unit 5: Understanding .NET Assemblies & Libaries · Unit 5: Understanding .NET Assemblies & Libraries 4 Prof. Sushant S Sundikar C# .Net Programming A multifile assembly, on the other

Unit 5: Understanding .NET Assemblies & Libraries 12

Prof. Sushant S Sundikar C# .Net Programming

OpenRead() Creates a read-only FileStream

OpenText() Creates a StreamReader type (described later) that reads from an existing text

file

OpenWrite() Creates a write-only FileStream type

The FileInfo.Create() Method

The first way you can create a file handle is to make use of the FileInfo.Create() method:

public class Program

{

static void Main(string[] args)

{

// Make a new file on the C drive.

FileInfo f = new FileInfo(@"C:\Test.dat");

FileStream fs = f.Create();

// Use the FileStream object Close down file stream.

fs.Close();

}

}

The FileInfo.Open() Method

You can use the FileInfo.Open() method to open existing files as well as create new files with far

more precision than FileInfo.Create(). Once the call to Open() completes, you are returned a

FileStream object.

Example:

static void Main(string[] args)

{

// Make a new file via FileInfo.Open().

FileInfo f2 = new FileInfo(@"C:\Test2.dat");

FileStream fs2 = f2.Open( FileMode.OpenOrCreate,

FileAccess.ReadWrite, FileShare.None);

// Use the FileStream object...

Page 13: Unit 5: Understanding .NET Assemblies & Libaries · Unit 5: Understanding .NET Assemblies & Libraries 4 Prof. Sushant S Sundikar C# .Net Programming A multifile assembly, on the other

Unit 5: Understanding .NET Assemblies & Libraries 13

Prof. Sushant S Sundikar C# .Net Programming

// Close down file stream.

fs2.Close();

}

TheOpen() method requires three parameters. The first parameter specifies the general flavor of the

I/O request (e.g., make a new file, open an existing file, append to a file, etc.), which is specified

using the FileMode enumeration:

public enum FileMode

{

// Specifies that the operating system should create a new file.

// If the file already exists, a System.IO.IOException is thrown.

CreateNew,

// Specifies that the operating system should create a new file.

// If the file already exists, it will be overwritten.

Create, Open,

// Specifies that the operating system should open a file if it

exists; otherwise, a new file should be created.

OpenOrCreate, Truncate, Append

}

The second parameter, a value from the FileAccess enumeration, is used to determine the

read/write behavior of the underlying stream:

public enum FileAccess

{

Read,

Write,

ReadWrite

}

Finally, you have the third parameter, FileShare, which specifies how the file is to be shared among

other file handlers. Here are the core names:

public enum FileShare

{

None,

Read,

Write,

ReadWrite

}

Page 14: Unit 5: Understanding .NET Assemblies & Libaries · Unit 5: Understanding .NET Assemblies & Libraries 4 Prof. Sushant S Sundikar C# .Net Programming A multifile assembly, on the other

Unit 5: Understanding .NET Assemblies & Libraries 14

Prof. Sushant S Sundikar C# .Net Programming

Working with the File Type

Provides static methods for the creation, copying, deletion, moving, and opening of files, and aids in

the creation of FileStream objects.

Use the File class for typical operations such as copying, moving, renaming, creating, opening,

deleting, and appending to files. You can also use the File class to get and set file attributes or

DateTime information related to the creation, access, and writing of a file. By default, full read/write

access to new files is granted to all users.

Unlike FileInfo, the File type supports a few unique members

Method Meaning in Life

ReadAllBytes() Opens the specified file, returns the binary data as an array of bytes, and

then closes the file

ReadAllLines() Opens a specified file, returns the character data as an array of strings, and

then closes the file

ReadAllText() Opens a specified file, returns the character data as a System.String, and then

closes the file

WriteAllBytes() Opens the specified file, writes out the byte array, and then closes the file

WriteAllLines() Opens a specified file, writes out an array of strings, and then closes the file

WriteAllText() Opens a specified file, writes the character data, and then closes the file

Example:

class Program

{

static void Main(string[] args)

{

string[] myTasks = {

"Fix bathroom sink",

"Call Dave",

"Call Mom and Dad",

"Play XBox"};

// Write out all data to file on C drive.

File.WriteAllLines(@"C:\tasks.txt", myTasks);

// Read it all back and print out.

foreach (string task in

File.ReadAllLines(@"C:\tasks.txt"))

{

Console.WriteLine("TODO: {0}", task);

}

Page 15: Unit 5: Understanding .NET Assemblies & Libaries · Unit 5: Understanding .NET Assemblies & Libraries 4 Prof. Sushant S Sundikar C# .Net Programming A multifile assembly, on the other

Unit 5: Understanding .NET Assemblies & Libraries 15

Prof. Sushant S Sundikar C# .Net Programming

}

}

Working with BinaryWriters and BinaryReaders

BinaryReader and BinaryWriter, types allow 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. In addition to Write(), BinaryWriter

provides additional members which are displayed in the tables below:

Table 5-5. BinaryWriter Core Members

Member Meaning in Life

BaseStream

BinaryWriter

This read-only property provides access to the underlying stream

used with the object.

Close() This method closes the binary stream.

Flush() This method flushes the binary stream.

Seek() This method sets the position in the current stream.

Write() This method writes a value to the current stream.

Table 5-6. BinaryReader Core Members

Member Meaning in Life

BaseStream

BinaryReader

This read-only property provides access to the underlying stream used

with the object.

Close() This method closes the binary reader.

PeekChar() This method returns the next available character without actually

advancing the position in the stream.

Read() This method reads a given set of bytes or characters and stores them

in the incoming array.

ReadXXXX() The BinaryReader class defines numerous ReadXXXX() methods that

grab the next type from the stream (ReadBoolean(), ReadByte(),

ReadInt32(), and so forth).

Example:

The following example writes a number of data types to a new *.dat file:

static void Main(string[] args)

Page 16: Unit 5: Understanding .NET Assemblies & Libaries · Unit 5: Understanding .NET Assemblies & Libraries 4 Prof. Sushant S Sundikar C# .Net Programming A multifile assembly, on the other

Unit 5: Understanding .NET Assemblies & Libraries 16

Prof. Sushant S Sundikar C# .Net Programming

{

// Open a binary writer for a file.

FileInfo f = new FileInfo("BinFile.dat");

BinaryWriter bw = new BinaryWriter(f.OpenWrite());

// Print out the type of BaseStream.

// (System.IO.FileStream in this case).

Console.WriteLine("Base stream is: {0}", bw.BaseStream);

// Create some data to save in the file

double aDouble = 1234.67;

int anInt = 34567;

char[] aCharArray = { 'A', 'B', 'C' };

// Write the data

bw.Write(aDouble);

bw.Write(anInt);

bw.Write(aCharArray);

bw.Close();

// Read the data as raw bytes

BinaryReader br = new BinaryReader(f.OpenRead());

int temp = 0;

while (br.PeekChar() != -1)

{

Console.Write("{0,7:x} ", br.ReadByte());

if (++temp == 4)

{

// Write a new line every 4 bytes

Console.WriteLine();

temp = 0;

}

}

Console.WriteLine();

}

Working with StreamWriters and StreamReaders

The StreamWriter and StreamReader classes are useful whenever you need to read or write

characterbased data (e.g., strings). Both of these types work by default with Unicode characters.

StreamReader derives from an abstract type named TextReader, as does the related StringReader

Type. The StreamWriter type (as well as StringWriter, also examined later in this chapter) derives

from an abstract base class named TextWriter. This class defines members that allow derived types

to write textual data to a given character stream. The relationship between each of these new I/O

centric types is shown in figure below:

Page 17: Unit 5: Understanding .NET Assemblies & Libaries · Unit 5: Understanding .NET Assemblies & Libraries 4 Prof. Sushant S Sundikar C# .Net Programming A multifile assembly, on the other

Unit 5: Understanding .NET Assemblies & Libraries 17

Prof. Sushant S Sundikar C# .Net Programming

Figure: Readers and Writers

To help in your understanding of the core writing capabilities of the StreamWriter and StringWriter

classes, Table below describes the core members of the abstract TextWriter base class.

Member Meaning in Life

Close() Closes the writer and frees any associated resources. In the process, the buffer

is automatically flushed.

Flush() Clears all buffers for the current writer and causes any buffered data to be

written to the underlying device, but does not close the writer.

NewLine Indicates the newline constant for the derived writer class. The default line

terminator is a carriage return followed by a line feed (\r\n).

Write() Writes a line to the text stream without a newline constant.

WriteLine() Writes a line to the text stream with a newline constant.

The derived StreamWriter class provides an appropriate implementation for the Write(), Close(), and

Flush() methods, and it defines the additional AutoFlush property. This property, when set to true,

forces StreamWriter to flush all data every time you perform a write operation. Be aware that you

can gain better performance by setting AutoFlush to false, provided you always call Close() when you

are done writing with a StreamWriter.

Writing to a Text File

static void Main(string[] args)

{

Console.WriteLine("***** Fun with StreamWriter / StreamReader *****\n");

// Get a StreamWriter and write string data.

StreamWriter writer = File.CreateText("reminders.txt");

Page 18: Unit 5: Understanding .NET Assemblies & Libaries · Unit 5: Understanding .NET Assemblies & Libraries 4 Prof. Sushant S Sundikar C# .Net Programming A multifile assembly, on the other

Unit 5: Understanding .NET Assemblies & Libraries 18

Prof. Sushant S Sundikar C# .Net Programming

writer.WriteLine("Don't forget Mother's Day this year...");

writer.WriteLine("Don't forget Father's Day this year...");

writer.WriteLine("Don't forget these numbers:");

for(int i = 0; i < 10; i++)

writer.Write(i + " ");

// Insert a new line.

writer.Write(writer.NewLine);

// Closing automatically flushes!

writer.Close();

Console.WriteLine("Created file and wrote some thoughts...");

}

Output:

Reading from a Text File

StreamReader type derives from TextReader, which offers the functionality described in Table

below.

Table: TextReader Core Members

Member Meaning in Life

Peek() Returns the next available character without actually changing the position of

the reader. A value of –1 indicates you are at the end of the stream.

Read() Reads data from an input stream.

ReadBlock() Reads a maximum of count characters from the current stream and writes

thedata to a buffer, beginning at index.

ReadLine() Reads a line of characters from the current stream and returns the data as a

string (a null string indicates EOF).

ReadToEnd() Reads all characters from the current position to the end of the stream and

returns them as a single string.

static void Main(string[] args)

{

Console.WriteLine("***** Fun with StreamWriter / StreamReader *****\n");

...

Page 19: Unit 5: Understanding .NET Assemblies & Libaries · Unit 5: Understanding .NET Assemblies & Libraries 4 Prof. Sushant S Sundikar C# .Net Programming A multifile assembly, on the other

Unit 5: Understanding .NET Assemblies & Libraries 19

Prof. Sushant S Sundikar C# .Net Programming

// Now read data from file.

Console.WriteLine("Here are your thoughts:\n");

StreamReader sr = File.OpenText("reminders.txt");

string input = null;

while ((input = sr.ReadLine()) != null)

{

Console.WriteLine (input);

}

}

Working with StringWriters and StringReaders

Using the StringWriter and StringReader types, you can 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. To illustrate, the following example writes a block of string data to a

StringWriter object rather than a file on the local hard drive:

static void Main(string[] args)

{

Console.WriteLine("***** Fun with StringWriter / StringReader

*****\n");

// Create a StringWriter and emit character data to memory.

StringWriter strWriter = new StringWriter();

strWriter.WriteLine("Don't forget Mother's Day this year...");

strWriter.Close();

// Get a copy of the contents (stored in a string) and pump

// to console.

Console.WriteLine("Contents of StringWriter:\n{0}", strWriter);

}

Because StringWriter and StreamWriter both derive from the same base class (TextWriter), the

writing logic is more or less identical. However, given that nature of StringWriter, be aware that this

class allows you to extract a System.Text.StringBuilder object via the GetStringBuilder() method:

Page 20: Unit 5: Understanding .NET Assemblies & Libaries · Unit 5: Understanding .NET Assemblies & Libraries 4 Prof. Sushant S Sundikar C# .Net Programming A multifile assembly, on the other

Unit 5: Understanding .NET Assemblies & Libraries 20

Prof. Sushant S Sundikar C# .Net Programming

// Create a StringWriter and emit character data to memory.

StringWriter strWriter = new StringWriter();

// Get the internal StringBuilder.

StringBuilder sb = strWriter.GetStringBuilder();

sb.Insert(0, "Hey!! ");

When you wish to read from a stream of character data, make use of the corresponding

StringReader type, which (as you would expect) functions identically to the related StreamReader

class. In fact, the StringReader class does nothing more than override the inherited members to read

from a block of character data, rather than a file, as shown here:

static void Main(string[] args)

{

Console.WriteLine("***** Fun with StringWriter / StringReader

*****\n");

// Create a StringWriter and emit character data to memory.

StringWriter strWriter = new StringWriter();

...

// Read data from the StringWriter.

StringReader strReader = new StringReader(writer.ToString());

string input = null;

while ((input = strReader.ReadLine()) != null)

{

Console.WriteLine (input);

}

strReader.Close();

}

Programmatically “Watching” Files

Now that you have a better handle on the use of various readers and writers, next you’ll look at the

role of the FileSystemWatcher class. This type can be quite helpful when you wish to

programmatically monitor (or “watch”) files on your system. Specifically, the FileSystemWatcher

type can be instructed to monitor files for any of the actions specified by the NotifyFilters

enumeration.

public enum System.IO.NotifyFilters

{

Attributes, CreationTime,

DirectoryName, FileName,

LastAccess, LastWrite,

Security, Size,

Page 21: Unit 5: Understanding .NET Assemblies & Libaries · Unit 5: Understanding .NET Assemblies & Libraries 4 Prof. Sushant S Sundikar C# .Net Programming A multifile assembly, on the other

Unit 5: Understanding .NET Assemblies & Libraries 21

Prof. Sushant S Sundikar C# .Net Programming

}

The first step you will need to take to work with the FileSystemWatcher type is to set the Path

property to specify the name (and location) of the directory that contains the files to be monitored,

as well as the Filter property that defines the file extensions of the files to be monitored.

To illustrate the process of watching a file, assume you have created a new directory on your C drive

named MyFolder that contains various *.txt files (named whatever you wish). The following console

application will monitor the *.txt files within the MyFolder and print out messages in the event that

the files are created, deleted, modified, or renamed:

static void Main(string[] args)

{

Console.WriteLine("***** The Amazing File Watcher App *****\n");

// Establish the path to the directory to watch.

FileSystemWatcher watcher = new FileSystemWatcher();

try{

watcher.Path = @"C:\MyFolder";

}

catch(ArgumentException ex) {

Console.WriteLine(ex.Message);

return;

}

// Set up the things to be on the // lookout for.

watcher.NotifyFilter = NotifyFilters.LastAccess

| NotifyFilters.LastWrite

| NotifyFilters.FileName

| NotifyFilters.DirectoryName;

// Only watch text files.

watcher.Filter = "*.txt";

// Add event handlers.

watcher.Changed += new FileSystemEventHandler(OnChanged);

watcher.Created += new FileSystemEventHandler(OnChanged);

watcher.Deleted += new FileSystemEventHandler(OnChanged);

watcher.Renamed += new RenamedEventHandler(OnRenamed);

// Begin watching the directory.

watcher.EnableRaisingEvents = true;

// Wait for the user to quit the program.

Console.WriteLine(@"Press 'q' to quit app.");

while(Console.Read()!='q');

}

The two event handlers simply print out the current file modification:

static void OnChanged(object source, FileSystemEventArgs e)

{

// Specify what is done when a file is changed, created, or deleted.

Console.WriteLine("File: {0} {1}!", e.FullPath, e.ChangeType);

}

Page 22: Unit 5: Understanding .NET Assemblies & Libaries · Unit 5: Understanding .NET Assemblies & Libraries 4 Prof. Sushant S Sundikar C# .Net Programming A multifile assembly, on the other

Unit 5: Understanding .NET Assemblies & Libraries 22

Prof. Sushant S Sundikar C# .Net Programming

static void OnRenamed(object source, RenamedEventArgs e)

{

// Specify what is done when a file is renamed.

Console.WriteLine("File: {0} renamed to\n{1}", e.OldFullPath,

e.FullPath);

}

To test this program, run the application and open Windows Explorer. Try renaming your files,

creating a *.txt file, deleting a *.txt file, or whatnot. You will see the console application print out

various bits of information regarding the state of the text files within MyFolder( see figure below)


Recommended