The File System

This section covers the classes that provide access to the file system. Creating, copying, and deleting files and directories are handled in Java by the java.io.File class. A slightly different approach is taken by .NET, but the end result is much the same. We end this section with a comparison of the Java and .NET file system methods.

Paths

The System.IO.Path class contains a series of static utility methods used to manipulate strings representing file and directory paths. With the exception of the GetTempFileName method, the Path class does not interact with the file system.

Although the Path class provides little functionality that can’t be achieved using string parsing and regular expressions, it is designed to provide cross-platform support. When the .NET Framework is ported to other platforms, applications that utilize the Path class should work seamlessly.

Note

When using the Path class to formulate file paths, bear in mind that although the class ensures that paths do not contain illegal characters, no checks are made to ensure that the path is valid on the local system.

Table 10-3 summarizes the methods and fields of the Path class.

Table 10-3. The Path Class

Member

Comments

DirectorySeparatorChar

The platform-specific separator character. Defaults to for Windows.

InvalidPathChars

Provides a platform-specific array of characters that are illegal in path names.

PathSeparator

Provides a platform-specific path separator character. Defaults to ; for Windows.

VolumeSeparatorChar

Provides a platform-specific volume separator character. Defaults to : for Windows.

ChangeExtension()

Changes the extension of a path string.

Combine()

Concatenates two path strings.

GetDirectoryName()

Gets the contents of a path string between the first and last instances of DirectorySeparatorChar.

GetExtension()

Returns the extension of a path string, including the period.

GetFileName()

Returns the contents of a path string after the last instance of DirectorySeparatorChar.

GetFileNameWithoutExtension()

Returns the contents of a path string after the last instance of DirectorySeparatorChar and before the last period.

GetFullPath()

Returns a fully qualified path for a partial path string. If the partial path begins with the directory separator character, the result will be prepended with <default drive>:; otherwise, the result will be the current working directory plus the partial path name.

GetPathRoot()

Returns the root for a path string.

GetTempFileName()

Creates a zero-length temporary file with a unique path, which is returned as the result.

GetTempPath()

Returns the path of the current system’s temporary directory.

HasExtension()

Returns true if the path string contains the period character followed by at least one other character.

IsPathRooted()

Returns true if the path is fully qualified.

Files and Directories

Java handles interrogating the file system through a single class, java.io.File. .NET breaks the same functionality up into four separate classes, which provides some flexibility. We feel, however, that this results in an overly complex approach that can be frustrating to work with.

Two classes contain static methods for managing the file system. The System.IO.Directory class provides methods to create, move, and manage directories, while the System.IO.File class offers the same services for files. Every call to a method in one of these classes requires a string containing the name of the desired file or directory.

These classes are supplemented by System.IO.DirectoryInfo and System.IO.FileInfo, which offer largely the same functionality as Directory and File but require instantiation prior to use. Instances of DirectoryInfo and FileInfo are created by passing a path string into the constructor, resulting in better efficiency if multiple operations are performed on the same file or directory.

The following example demonstrates how to write out the creation time for a file using a FileInfo instance and with the static methods of the File class:

FileInfo x_fileinfo = new FileInfo("myfile.txt");
Console.WriteLine(x_fileinfo.CreationTime);

Console.WriteLine(File.GetCreationTime("myfile.txt"));

Differentiating Between Files and Directories

Our principal complaint about these classes is that it’s difficult to determine whether a path represents a file or a directory. The Java java.io.File class provides the isDirectory method, but the .NET classes don’t offer anything so simple.

There are two approaches to determining the status of a path: the first relies on the behavior of the Exists methods in the File, FileInfo, Directory, and DirectoryInfo classes, and the second uses a bitwise operation on the attribute sets exposed by FileInfo and DirectoryInfo.

Using the Exists methods

The Exists method in the Directory class will return true only if a path represents a directory in the file system. The Exists method in the File class will return true only if the path represents a file in the file system. These behaviors can be combined to determine whether a path represents a file, represents a directory, or doesn’t exist in the file system. The following code fragment demonstrates this approach:

string x_path = "C:\mypath\myfile.txt";
if (Directory.Exists(x_path)) {
    Console.WriteLine("{0} is a directory", x_path);
} else if (File.Exists(x_path)) {
    Console.WriteLine("{0} is a file", x_path);
} else {
    Console.WriteLine("{0} does not exist", x_path);
}

Using bitwise operations

Using bitwise operations is slightly more complicated than the foregoing approach. The FileInfo and DirectoryInfo classes provide an Attributes property, which is a bit flag enumeration containing file attributes, as listed in the System.IO.FileAttributes enumeration. This approach looks for the presence of the FileAttributes.Directory flag to differentiate between a file and a directory.

string x_path = "C:\mypath\myfile.txt";

FileInfo x_info = new FileInfo(x_path);

if ((ulong)x_info.Attributes == UInt64.MaxValue) {
    Console.WriteLine("{0} does not exist", x_path);
} else if ((x_info.Attributes & FileAttributes.Directory)
    == FileAttributes.Directory) {
        Console.WriteLine("{0} is a directory", x_path);
} else {
    Console.WriteLine("{0} is a file", x_path);
}

This fragment detects paths that relate to nonexistent files by checking to see whether the unsigned integer value of the attributes is the same as that of the UInt64.MaxValue field. The Microsoft documentation on the file attributes is a little hazy, and we’re not sure whether this is a bug or an expected behavior. For obvious reasons, we suggest using the Exists methods to tell files and directories apart.

Getting Streams from Files

As with Java, data is read from and written to files through use of a streams model. (See the Streams section later in this chapter for more details.) This section demonstrates how to get streams to access files. .NET provides several means to get a stream, but all result in the creation of a System.IO.FileStream instance. The FileStream class is the default stream for operations that are backed by a file. In .NET, streams can typically read and write data, so this class is roughly equivalent to a combination of java.io.FileOutputStream and java.io.FileInputStream.

Creating a stream directly

The most direct way to create a stream is to create a new instance of FileStream, passing in a path string to the constructor. Because .NET streams can be used to read and write data, details must be supplied about how the file is opened. The basic FileStream constructor takes the following form:

FileStream(string path, FileMode mode, FileAccesss access);

The FileMode enumeration argument indicates how the file should be opened. Table 10-4 describes the different FileMode enumeration members.

Table 10-4. Available Modes When Creating a New FileStream

System.IOFileStream Member

Description

Append

Opens the file and seeks to the end, creating the file if it doesn’t exist. Can be used for write operations only.

Create

Creates a new file if one doesn’t exist. Overwrites the file if it does exist.

CreateNew

Creates a new file. If the file already exists, an IOException is thrown.

Open

Opens a file. Throws a FileNotFoundException if the file doesn’t exist.

OpenOrCreate

Opens a file if one exists; creates a new file otherwise.

Truncate

Sets the file size to 0 and opens the file for writing. Can be used for write operations only.

The FileAccess argument specifies whether the file should be opened for reading, writing, or both, using values from the System.IO.FileAccess enumeration, which consists of Read, Write, and ReadWrite. The following statements demonstrate how these arguments can be combined:

// open an existing file for reading and writing
FileStream("myfile.txt", FileMode.Open, FileAccess.ReadWrite);

// truncate an existing file
FileStream("myfile.txt", FileMode.Truncate, FileAccess.Write);

// create a new file for reading
FileStream("mynewfile.txt", FileMode.CreateNew, FileAccess.Read);

The most comprehensive constructor takes the following form:

FileStream(string path, FileMode mode, FileAccesss access,
    FileShare share, int buffer, bool async);

The new elements are detailed next. In between the basic and comprehensive forms are several overloaded constructors that provide defaults for certain values. These are described in Table 10-5.

Table 10-5. Available FileStream Constructor Arguments

Constructor Argument

Description

FileShare access

Specifies how other processes access the file that has been opened. This argument provides a mapping onto the file lock. Valid values are contained in the System.IO.FileShare enumeration.

int buffer

The size of the buffer for the stream.

bool async

When set to true, asynchronous I/O will be enabled on the stream. See the Asynchronous I/O section later in this chapter for details.

Creating a stream indirectly

Instances of FileStream can also be created indirectly via the File and FileInfo classes. Both classes provide the same range of methods for this task, the difference being that the path name for the file must be passed into the static File methods. These classes can also be used to create instances of System.IO.StreamReader, which is covered in the Readers and Writers section later in this chapter. Table 10-6 lists the methods available in the File and FileInfo classes.

Table 10-6. Methods in the File and FileInfo Classes

Method

Description

File.Open()

FileInfo.Open()

Creates a FileStream using FileMode and FileAccess. Equivalent to using the FileStream constructor.

File.OpenRead()

FileInfo.OpenRead()

Opens a read-only stream. Equivalent to specifying the FileMode.Open and FileAccess.Read arguments.

File.OpenText()

FileInfo.OpenText()

File.AppendText()

FileInfo.AppendText()

File.CreateText()

FileInfo.CreateText()

Creates a StreamReader. See the Readers and Writers section later in this chapter for a description of this class.

File.OpenWrite()

FileInfo.OpenWrite()

Opens a write-only stream. Equivalent to using the FileMode.Open and FileAccess.Write arguments.

Comparison with Java

Although the class structure is different, most of the file system features from the java.io.File class can be found in the System.IO namespace. Table 10-7 provides the mapping between Java and the .NET classes. Where a method is listed from the File and Directory classes, there is typically a similar method in the FileInfo and DirectoryInfo classes.

Table 10-7. Comparison Between the Java and .NET File System Support Classes

Java

.NET

Comments

File(string path)

FileInfo(path)

DirInfo(path)

File system support is also provided by the static utility classes Directory and File.

canRead()

N/A

 

canWrite()

N/A

 

compareTo()

N/A

 

createNewFile()

File.Create()

Directory.Create()

 

createTempFile()

Path.GetTempFileName()

 

delete()

File.Delete()

Directory.Delete()

 

deleteOnExit()

N/A

 

exists()

File.Exists()

Directory.Exists()

 

getAbsolutePath()

N/A

 

getAbsoluteName()

  

getCanonicalPath()

Path.GetFullPath()

 

getCanonicalName()

  

getName()

Path.GetFileName()

 

getParent()

Path.GetDirectoryName()

 
 

Directory.GetParent()

 

isAbsolute()

Path.IsPathRooted()

 

isFile()

isDirectory()

File.Exists()

Directory.Exists()

See the Differentiating Between Files and Directories section earlier for more details.

isHidden()

File.GetAttributes().Hidden

Directory.GetAttributes().Hidden

 

lastModified()

File.GetLastWriteTime()

Directory.GetLastWriteTime()

 

length()

FileInfo.Length

 

listFiles()

Directory.GetFileSystemEntries()

Directory.GetFiles()

Directory.GetDirectories()

 

listRoots()

Directory.GetLogicalDrives()

 

mkdir()

Directory.CreateDirectory()

 

mkdirs()

  

renameTo()

Directory.Move()

File.Move()

 

setLastModified()

File.SetLastWriteTime()

Directory.SetLastWriteTime()

 

isReadOnly()

File.Attributes.ReadOnly

 

N/A

File.Copy()

Copies a file to a new location.

N/A

File.GetAttributes()

Returns the set of attributes for a file or directory.

Directory.GetAttributes()

N/A

File.SetAttributes()

Sets the attributes for a file or directory.

Directory.SetAttributes()

N/A

File.SetCreationTime()

File.GetCreationTime()

File.SetLastAccessTime()

File.GetLastAccessTime()

Directory.SetCreationTime()

Directory.GetCreationTime()

Directory.SetLastAccessTime()

Directory.GetLastAccessTime()

Gets or sets the time that a file or directory was created or accessed.

N/A

Directory.GetCurrentDirectory()

Available in Java through the user.dir system property.

 

Directory.SetCurrentDirectory()

 
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset