15.6. Readers and Writers

The Stream class and its subclasses are used for byte-level input/output. For actual character I/O, you should use System.IO.TextWriter and System.IO.TextReader.

The TextWriter class has several overloaded Write methods that write primitives to the underlying medium. All these methods write the primitive values as strings. The WriteLine method of this class writes the data and follows it with the line terminator character. The TextReader class has matching methods for reading data one character at a time (using the Read()method), reading a sequence of characters into a char[], or reading a line of characters.

You must be careful about using the ReadLine method; sometimes a line can be extremely long, and although the TextReader class maintains an internal buffer for storing the read characters of the line, it can throw an OutOfMemoryException for long lines.

Both TextWriter and TextReader are abstract classes, and therefore the two subclasses StreamWriter and StreamReader are typically used to harness the reader/writer functionality. ReadLine() and WriteLine() are two convenient methods for reading and writing text data to a file.

Listing 15.4 shows the usage of the reader and writer classes.

Listing 15.4. Using StreamWriter and StreamReader to Read and Write Text Files (C#)
using System;
using System.IO;
public class Test {
  private const string PATH = "c:\Book\test.txt";
  public static void Main(string[] args) {
    StreamWriter sw = null;
    try {
      sw = CreateFile();
      WriteText(sw);
      ReadText(sw);
    } catch (IOException e) {
      Console.WriteLine(e.StackTrace);
    } finally {
      if (sw != null) sw.Close();
    }
  }
  private static StreamWriter CreateFile() {
    FileStream fs = new FileStream(PATH,FileMode.OpenOrCreate,
                         FileAccess.ReadWrite, FileShare.None);
    return new StreamWriter(fs); // (1)
  }
  private static void WriteText(StreamWriter sw) {
    sw.WriteLine("Testing the StreamWriter capabilities");
    sw.WriteLine("Writing Boolean {0}",true);
    sw.WriteLine("Writing Float {0}",6.78);
    sw.WriteLine("Writing Long {0}",4576457L);
    sw.Write(455);
    sw.WriteLine(new Person("jack"));
    sw.Flush();
  }
  private static void ReadText(StreamWriter sw) {
    StreamReader sr = new StreamReader(sw.BaseStream); //(2)
    sr.BaseStream.Seek(0, SeekOrigin.Begin);
    while (sr.Peek() > 1) {
      Console.WriteLine(sr.ReadLine());
    }
  }
}
class Person {
  string name;
  public Person(string name) { this.name = name; }
}

The output of Listing 15.4 is as follows:

Testing the StreamWriter capabilities
Writing Boolean True
Writing Float 6.78
Writing Long 4576457
455Person

Note that you can write most of the primitives in their textual form to the file. You can also write a custom object to the file, as shown by writing the Person object. The ToString() method of the custom object is automatically invoked when the object is written.

Note that this is not the “correct” way to store the state of an object. To correctly store an object to the disk file, you must serialize it, as you will see in later sections. Writing the Person object is shown here merely to illustrate the available API calls. The file was created with the FileMode of OpenOrCreate, thereby allowing the file to be opened if it was previously created. The FileAccess enumeration is changed to ReadWrite because we are reading and writing in the same program. Both StreamWriter and StreamReader default to UTF-8 encoding unless otherwise specified. UTF-8 handles Unicode characters correctly and provides consistent results on localized versions of the operating system.

If StreamWriter and StreamReader have different encodings, you can get interesting results. For example, suppose you change (1) in Listing 15.4 to the following:

return new StreamWriter(fs, System.Text.Encoding.ASCII);

Further suppose you change (2) to

StreamReader sr = new
StreamReader(sw.BaseStream,System.Text.Encoding.BigEndian
Unicode);

After these changes, you fill get the following output:

?????????????????????????????????????????????????????????

As you can see, the type of encoding can affect your “view” of the file's contents. By default, the StreamWriter and the StreamReader classes are not thread-safe. The StreamWriter.Synchronized() and StreamReader.Synchronized() static methods should be used to create thread-safe wrappers around these classes.

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

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