.NET Framework written application is able to run on different platform. Each platform uses a different end-of-line (EOL) character. You want your code to output the correct EOL character without having to write code to handle the EOL character specially for each platform.
When you are first learning the .NET Framework and even for some time after the proper way to read to, write from, or otherwise interact with files can be unclear because the framework provides so many different ways of attacking this problem. How should you determine which approach fits your scenario?
Use file streams to perform various file functions. There are five basic types of built-in file stream manipulation classes that you can use in order to read and/or write to the file stream:
|
There are other stream readers and writers (XmlTextReader/Writer, StringReader/Writer) that can also perform file stream functions but at a higher level. This article is meant for a more fundamental approach to file operations.
The most straightforward method of creating an object is to use the new keyword. The FileStream class has several overloaded class constructors that enable creating a new FileStream from scratch. The FileStream’s constructor enables a new FileStream object to be created from either a filename or a file handle.
The FileStream constructor can also accept a FileAccess, FileMode, and/or FileShare enumeration value. These enumeration values are defined in Tables as following.
FileMode enumeration values
|
FileAccess enumeration values
|
FileShare enumeration values
|
In addition to these enumerations that define how a file is opened, the FileStream constructor allows you to define whether this stream will be opened in a synchronous or asynchronous manner. This is the only class?f the ones discussed in this article that allows a file to be opened in an asynchronous manner.
The FileStream class also has methods for seeking to a point within a file stream, as well as locking or unlocking a portion or an entire file; locking will prevent other processes or threads from modifying the file. The other stream types discussed in this article do not have the ability to lock or unlock portions or an entire file. This locking/unlocking functionality cannot even be accessed through the BaseStream property of any of these types. Seeking within a file can be done directly using the BinaryReader or BinaryWriter classes. The StreamReader and StreamWriter classes cannot directly access the seek functionality. However, by using the BaseStream property of either the StreamReader or StreamWriter classes, the base stream’s seek functionality can be used.
FileStreams can also be created using the static methods of the File class. The table below shows these methods,
along with their equivalent FileStream object constructor parameters.
Static methods of the File class and their equivalent FileStream constructor calls
|
The File.Open method is overloaded to accept FileMode, FileAccess, and
FileShare enumeration values. The FileStream constructor is also
overloaded to accept these same parameters. Therefore, to make an equivalent FileStream constructor for the File.Open method, we need to use the same parameters for each of these three enumeration values in both parameter lists.
The File class has a complementary class called FileInfo that contains similar methods, but these methods are instance, not static, methods. Table below shows the FileInfo methods, which are similar to the File static methods, along with their equivalent FileStream object constructor parameters.
Instance methods of the FileInfo class and equivalent FileStream constructor calls
|
The FileInfo.Open instance method is overloaded to accept FileMode,
FileAccess, and FileShare enumeration values. These values should be
matched in the FileStream constructor parameter list.
The StreamReader and StreamWriter objects can be created using their
overloaded constructors. These overloaded constructors accept as parameters either a file path and name or a
FileStream object. Therefore, we can use any of the previously mentioned ways of creating a
FileStream object in the construction of either a StreamReader or
StreamWriter object.
In addition, we can use three of the static methods in the File class or three of the instance
methods in the FileInfo class to create a StreamReader or
StreamWriter object. Table below describes the static methods of the File
class used to create StreamReader and StreamWriter objects and
their equivalent StreamReader and StreamWriter object constructor
parameters.
Static methods of the File class and their equivalent StreamReader/StreamWriter constructor calls
|
Table below describes the instance methods of the FileInfo class used to create StreamReader and StreamWriter object and their equivalent StreamReader and StreamWriter object constructor parameters.
Instance methods of the FileInfo class and their equivalent StreamReader/StreamWriter constructor calls
|
The methods of the File and FileInfo classes do not return BinaryReader and BinaryWriter classes; therefore, we rely on their constructors to create these types of objects. The overloaded BinaryReader and BinaryWriter class constructors accept only a Stream object; they do not accept a filename.
To create a BinaryReader or BinaryWriter object, we first need to create a StreamM type object. Since Stream is an abstract class, we need to create one of its derived classes, such as the FileStream class. Any of the prior ways of creating a FileStream object may be employed as a parameter in the constructor of either a BinaryReader or BinaryWriter. The following code creates both a BinaryReader and a BinaryWriter object from a single FileStream object:
fileStream = File.Create("filename.file"); BinaryWriter binaryWriter1 = new BinaryWriter(fileStream); BinaryReader binaryReader1 = new BinaryReader(fileStream);
There are many different ways of combining the techniques discussed in this article to create and open files. For example, if you require file locking and/or asynchronous file processing, you will need a FileStream object. If you are
dealing with text streams in memory and on disk, perhaps the StreamReader and StreamWriter might be a better choice. Finally, if you are dealing with binary data or mixed binary and text data in different encodings, you should consider BinaryReader and BinaryWriter.
Here are a few examples of using the various built-in streams:
// create a temp file to work with string tempFile = Path.GetTempFileName(); // FileStream FileStream fileStream = null; try { // open the file fileStream = File.Open(tempFile, FileMode.Append); string text = "Hello World "; byte[] bytes = Encoding.ASCII.GetBytes(text.ToCharArray()); // write to the file fileStream.Write(bytes, 0, bytes.Length); } finally { //make sure the file is closed if it was opened if (fileStream != null) fileStream.Close(); } // StreamReader StreamReader streamReader = null; try { streamReader = new StreamReader(tempFile); char[] chars = new char[64]; // read a block of characters streamReader.Read(chars, 0, 64); string charsFound = new string(chars); Console.WriteLine("Chars in stream {0}", charsFound); } finally { if (streamReader != null) streamReader.Close(); } // StreamWriter StreamWriter streamWriter = null; try { // open for append streamWriter = new StreamWriter(tempFile, true); // append some text streamWriter.WriteLine(", It''s the StreamWriter!"); } finally { if (streamWriter != null) streamWriter.Close(); } // BinaryWriter BinaryWriter binaryWriter = null; long pos = 0; int twentyFive = 25; try { // start up the binary writer with the base stream from the streamwriter // since it is open binaryWriter = new BinaryWriter(streamWriter.BaseStream); // move to end pos = binaryWriter.Seek(0, SeekOrigin.End); // write out 25 binaryWriter.Write(twentyFive); } finally { // close up if (binaryWriter != null) binaryWriter.Close(); } // BinaryReader StreamReader streamReader2 = null; BinaryReader binaryReader = null; try { // open a new reader streamReader2 = new StreamReader(tempFile); binaryReader = new BinaryReader(streamReader2.BaseStream); // advance the stream to the number we stored for (long i=0; iint num = binaryReader.ReadInt32(); // is this the same number...? if (num == twentyFive) Console.WriteLine("Successfully read 25 back from stream"); else Console.WriteLine("Failed to successfully read 25 back from stream"); } finally { // close up if (binaryReader != null) binaryReader.Close(); // close stream if (streamReader2 != null) streamReader2.Close(); }
Popularity: 2% [?]
RSS feed for comments on this post · TrackBack URI
Leave a reply