Listing 25-15: Writing to a MemoryStream VB Dim data As Byte = System.Text.Encoding.ASCII.GetBytes"This is a string" Dim ms As New System.IO.MemoryStream ms.Writedata, 0, data.Length ms.
Trang 1FileStreamresources asClosedoes, it can be very useful if you are going to perform multiple write
operations and do not want to release and then reacquire the resources for each write operation
As you can see, so far reading and writing to files is really quite easy The good thing is that, as mentioned
earlier, because NET uses the same basicStreammodel for a variety of data stores, you can use these
same techniques for reading and writing to any of theStreamderived classes Listing 25-15 shows how
you can use the same basic code to write to aMemoryStream, and Listing 25-16 demonstrates reading a
Telnet server response using theNetworkStream
Listing 25-15: Writing to a MemoryStream
VB
Dim data() As Byte = System.Text.Encoding.ASCII.GetBytes("This is a string")
Dim ms As New System.IO.MemoryStream()
ms.Write(data, 0, data.Length)
ms.Close()
C#
byte[] data = System.Text.Encoding.ASCII.GetBytes("This is a string");
System.IO.MemoryStream ms = new System.IO.MemoryStream();
ms.Write(data, 0, data.Length);
ms.Close();
Listing 25-16: Reading from a NetworkStream
VB
Dim client As New System.Net.Sockets.TcpClient()
’ Note: You can find a large list of Telnet accessible
’ BBS systems at http://www.dmine.com/telnet/brieflist.htm
’ The WCS Online BBS (http://bbs.wcssoft.com)
Dim addr As System.Net.IPAddress = System.Net.IPAddress.Parse("65.182.234.52")
Dim endpoint As New System.Net.IPEndPoint(addr, 23)
client.Connect(endpoint)
Dim ns As System.Net.Sockets.NetworkStream = client.GetStream()
If (ns.DataAvailable) Then
Dim data(client.ReceiveBufferSize) As Byte
ns.Read(data, 0, client.ReceiveBufferSize)
Dim response As String = System.Text.Encoding.ASCII.GetString(data)
End If
ns.Close()
C#
System.Net.Sockets.TcpClient client = new System.Net.Sockets.TcpClient();
// Note: You can find a large list of Telnet accessible
// BBS systems at http://www.dmine.com/telnet/brieflist.htm
// The WCS Online BBS (http://bbs.wcssoft.com)
System.Net.IPAddress addr = System.Net.IPAddress.Parse("65.182.234.52");
System.Net.IPEndPoint endpoint = new System.Net.IPEndPoint(addr,23);
Trang 2System.Net.Sockets.NetworkStream ns = client.GetStream();
if (ns.DataAvailable)
{
byte[] bytes = new byte[client.ReceiveBufferSize];
ns.Read(bytes, 0, client.ReceiveBufferSize);
string data = System.Text.Encoding.ASCII.GetString(bytes);
}
ns.Close();
Notice that the concept in both examples is virtually identical You create aStreamobject, read the bytes into a byte array for processing, and then close the stream The code varies only in the implementation of specific Streams
Readers and Writers
Other main parts of I/O in the NET Framework areReaderandWriterclasses These classes help
insulate you from having to deal with reading and writing individual bytes to and from Streams, enabling you to concentrate on the data you are working with The NET Framework provides a wide variety of
reader and writer classes, each designed for reading or writing according to a specific set of rules The
first table following shows a partial list of the readers available in the NET Framework The second table lists the corresponding writer classes
Class Description
System.IO
.TextReader
Abstract class that enables the reading of a sequential series of characters
System.IO
.StreamReader
Reads characters from a byte stream Derived fromTextReader
System.IO
.StringReader
Reads textual information as a stream of in-memory characters Derived fromTextReader
System.IO
.BinaryReader
Reads primitive data types as binary values from a stream
System.Xml
.XmlTextReader
Provides fast, non-cached, forward-only access to XML
Class Description
System.IO
.TextWriter
Abstract class that enables the writing of a sequential series of characters
System.IO
.StreamWriter
Writes characters to a stream Derived fromTextWriter
System.IO
.StringWriter
Writes textual information as a stream of in-memory characters Derived fromTextWriter
Trang 3Class Description
System.IO
.BinaryWriter
Writes primitive data types in binary to a stream
System.Xml
.XmlTextWriter
Provides a fast, non-cached, forward-only way of generating XML streams
or files
Now look at using several different types of readers and writers, starting with a simple example
Listing 25-17 shows you how to use aStreamReaderto read aFileStream
Listing 25-17: Reading and writing a text file with a StreamReader
VB
Dim streamwriter As New System.IO.StreamWriter( _
System.IO.File.Open("C:\Wrox\temp.txt", System.IO.FileMode.Open) )
streamwriter.Write("This is a string")
streamwriter.Close()
Dim reader As New System.IO.StreamReader( _
System.IO.File.Open("C:\Wrox\temp.txt", System.IO.FileMode.Open) )
Dim tmp As String = reader.ReadToEnd()
reader.Close()
C#
System.IO.StreamWriter streamwriter =
new System.IO.StreamWriter(
System.IO.File.Open(@"C:\Wrox\temp.txt", System.IO.FileMode.Open) );
streamwriter.Write("This is a string");
streamwriter.Close();
System.IO.StreamReader reader =
new System.IO.StreamReader(
System.IO.File.Open(@"C:\Wrox\temp.txt",System.IO.FileMode.Open) );
string tmp = reader.ReadToEnd();
reader.Close();
Notice that when you create aStreamReader, you must pass an existing stream instance as a constructor
parameter The reader uses this stream as its underlying data source In this sample, you use theFile
class’s staticOpenmethod to open a writableFileStreamfor yourStreamWriter
Also notice that you no longer have to deal with byte arrays TheStreamReadertakes care of converting
the data to a type that’s more user-friendly than a byte array In this case, you are using theReadToEnd
method to read the entire stream and convert it to a string TheStreamReaderprovides a number of
different methods for reading data that you can use depending on exactly how you want to read the data,
from reading a single character using theReadmethod, to reading the entire file using theReadToEnd
method
Figure 25-12 shows the results of your write when you open the file in Notepad
Trang 4Figure 25-12
Now use theBinaryReaderandBinaryWriterclasses to read and write some primitive types to a file
TheBinaryWriterwrites primitive objects in their native format, so in order to read them using the
BinaryReader, you must select the appropriateReadmethod Listing 25-18 shows you how to do that; in this case, you are writing a value from a number of different primitive types to the text file, then reading the same value
Listing 25-18: Reading and writing binary data
VB
Dim binarywriter As New System.IO.BinaryWriter( _
System.IO.File.Create("C:\Wrox\binary.dat"))
binarywriter.Write("a string")
binarywriter.Write(&H12346789ABCDEF)
binarywriter.Write(&H12345678)
binarywriter.Write("c"c)
binarywriter.Write(1.5F)
binarywriter.Write(100.2D)
binarywriter.Close()
Dim binaryreader As New System.IO.BinaryReader( _
System.IO.File.Open("C:\Wrox\binary.dat", System.IO.FileMode.Open))
Dim a As String = binaryreader.ReadString()
Dim l As Long = binaryreader.ReadInt64()
Dim i As Integer = binaryreader.ReadInt32()
Dim c As Char = binaryreader.ReadChar()
Dim f As Double = binaryreader.ReadSingle()
Dim d As Decimal = binaryreader.ReadDecimal()
binaryreader.Close()
C#
System.IO.BinaryWriter binarywriter =
new System.IO.BinaryWriter(
System.IO.File.Create(@"C:\Wrox\binary.dat") );
binarywriter.Write("a string");
binarywriter.Write(0x12346789abcdef);
Continued
Trang 5binarywriter.Write(’c’);
binarywriter.Write(1.5f);
binarywriter.Write(100.2m);
binarywriter.Close();
System.IO.BinaryReader binaryreader =
new System.IO.BinaryReader(
System.IO.File.Open(@"C:\Wrox\binary.dat", System.IO.FileMode.Open));
string a = binaryreader.ReadString();
long l = binaryreader.ReadInt64();
int i = binaryreader.ReadInt32();
char c = binaryreader.ReadChar();
float f = binaryreader.ReadSingle();
decimal d = binaryreader.ReadDecimal();
binaryreader.Close();
If you open this file in Notepad, you should see that theBinaryWriterhas written the nonreadable binary
data to the file Figure 25-13 shows what the content of the file looks like TheBinaryReaderprovides a
number of different methods for reading various kinds of primitive types from the stream
In this sample, you use a differentReadmethod for each primitive type that you write to the file
Figure 25-13
Finally, notice that the basic usage of both theStreamReader/StreamWriterandBinaryReader/
BinaryWriterclasses is virtually identical You can apply the same basic ideas to use any of the reader
or writer classes
Encodings
TheStreamReaderby default attempts to determine the encoding format of the file If one of the
sup-ported encodings such as UTF-8 or UNICODE is detected, it is used If the encoding is not recognized,
the default encoding of UTF-8 is used Depending on the constructor you call, you can change the default
encoding used and optionally turn off encoding detection The following example shows how you can
control the encoding that theStreamReaderuses
StreamReader reader =
new StreamReader(@"C:\Wrox\text.txt",System.Text.Encoding.Unicode);
Trang 6The default encoding for theStreamWriteris also UTF-8, and you can override it in the same manner as theStreamReaderclass
I/O Shortcuts
Although knowing how to create and use streams is always very useful and worth studying, the NET
Framework provides you with numerous shortcuts for common tasks like reading and writing to files
For instance, if you want to read the entire file, you can simply use one of the static Read All methods
of theFileclass Using these methods, you cause NET to handle the process of creating theStreamand
StreamReaderfor you, and simply return the resulting string of data This is just one example of the
shortcuts that the NET Framework provides Listing 25-19 shows some of the others, with explanatory comments Keep in mind that Listing 25-19 is showing individual code snippets; do not try to run the
listing as a single block of code
Listing 25-19: Using the static method of the File and Directory classes
VB
’ Opens a file and returns a FileStream
Dim fs As System.IO FileStream = _
System.IO.File.Open("C:\Wrox\temp.txt", System.IO.FileMode.Open)
’ Opens a file and returns a StreamReader for reading the data
Dim sr As System.IO.StreamReader = System.IO.File.OpenText("C:\Wrox\temp.txt")
’ Opens a filestream for reading
Dim fs As System.IO.FileStream = System.IO.File.OpenRead("C:\Wrox\temp.txt")
’ Opens a filestream for writing
Dim fs As System.IO.FileStream = System.IO.File.OpenWrite("C:\Wrox\temp.txt")
’ Reads the entire file and returns a string of data
Dim data As String = System.IO.File.ReadAllText("C:\Wrox\temp.txt")
’ Writes the string of data to the file
System.IO.File.WriteAllText("C:\Wrox\temp.txt", data)
C#
// Opens a file and returns a FileStream
System.IO.FileStream fs =
System.IO.File.Open(@"C:\Wrox\temp.txt", System.IO.FileMode.Open);
// Opens a file and returns a StreamReader for reading the data
System.IO.StreamReader sr = System.IO.File.OpenText(@"C:\Wrox\temp.txt");
// Opens a filestream for reading
Continued
Trang 7System.IO.FileStream fs = System.IO.File.OpenRead(@"C:\Wrox\temp.txt");
// Opens a filestream for writing
System.IO.FileStream fs = System.IO.File.OpenWrite(@"C:\Wrox\temp.txt");
// Reads the entire file and returns a string of data
string data = System.IO.File.ReadAllText(@"C:\Wrox\temp.txt");
// Writes the string of data to the file
System.IO.File.WriteAllText(@"C:\Wrox\temp.txt", data);
Compressing Streams
Introduced in the NET 2.0 Framework, the System.IO.Compression namespace includes classes for
compressing and decompressing data using either theGZipStreamor theDeflateStreamclasses
GZip Compression
Because both new classes are derived from theStreamclass, using them should be relatively similar
to using the otherStreamoperations you have examined so far in this chapter Listing 25-20 shows an
example of compressing your text file using theGZipStreamclass
Listing 25-20: Compressing a file using GZipStream
VB
’ Read the file we are going to compress into a FileStream
Dim filename As String = Server.MapPath("TextFile.txt")
Dim infile As System.IO.FileStream = System.IO.File.OpenRead(filename)
Dim buffer(infile.Length) As Byte
infile.Read(buffer, 0, buffer.Length)
infile.Close()
’ Create the output file
Dim outfile As System.IO.FileStream = _
System.IO.File.Create(System.IO.Path.ChangeExtension(filename, "zip"))
’ Compress the input stream and write it to the output FileStream
Dim gzipStream As New System.IO.Compression.GZipStream(
outfile, System.IO.Compression.CompressionMode.Compress)
gzipStream.Write(buffer, 0, buffer.Length)
gzipStream.Close()
C#
// Read the file we are going to compress into a FileStream
string filename = Server.MapPath("TextFile.txt");
System.IO.FileStream infile = System.IO.File.OpenRead(filename);
byte[] buffer = new byte[infile.Length];
Trang 8infile.Read(buffer, 0, buffer.Length);
infile.Close();
// Create the output file
System.IO.FileStream outfile =
System.IO.File.Create(System.IO.Path.ChangeExtension(filename, "zip"));
// Compress the input stream and write it to the output FileStream
System.IO.Compression.GZipStream gzipStream =
new System.IO.Compression.GZipStream(outfile,
System.IO.Compression.CompressionMode.Compress);
gzipStream.Write(buffer, 0, buffer.Length);
gzipStream.Close();
Notice that theGZipStreamconstructor requires two parameters, the stream to write the compressed data
to, and theCompressionModeenumeration, which tells the class if you want to compress or decompress data After the code runs, be sure there is a file calledtext.zipin your Web site directory
Deflate Compression
TheCompressionnamespace also allows to you decompress a file using theGZiporDeflatemethods
Listing 25-21 shows an example of decompressing a file using theDeflatemethod
Listing 25-21: Decompressing a file using DeflateStream
VB
Dim filename As String = Server.MapPath("TextFile.zip")
Dim infile As System.IO.FileStream = System.IO.File.OpenRead(filename)
Dim deflateStream As New System.IO.Compression.DeflateStream( _
infile, System.IO.Compression.CompressionMode.Decompress)
Dim buffer(infile.Length + 100) As Byte
Dim offset As Integer = 0
Dim totalCount As Integer = 0
While True
Dim bytesRead As Integer = deflateStream.Read(buffer, offset, 100)
If bytesRead = 0 Then
Exit While End If
offset += bytesRead
totalCount += bytesRead
End While
Dim outfile As System.IO.FileStream = _
System.IO.File.Create(System.IO.Path.ChangeExtension(filename, "txt"))
outfile.Write(buffer, 0, buffer.Length)
outfile.Close()
C#
string filename = Server.MapPath("TextFile.zip");
System.IO.FileStream infile = System.IO.File.OpenRead(filename);
Continued
Trang 9System.IO.Compression.DeflateStream deflateStream =
new System.IO.Compression.DeflateStream(infile,
System.IO.Compression.CompressionMode.Decompress);
byte[] buffer = new byte[infile.Length + 100];
int offset = 0;
int totalCount = 0;
while (true)
{
int bytesRead = deflateStream.Read(buffer, offset, 100);
if (bytesRead == 0)
{ break; }
offset += bytesRead;
totalCount += bytesRead;
}
System.IO.FileStream outfile =
System.IO.File.Create(System.IO.Path.ChangeExtension(filename, "txt"));
outfile.Write(buffer, 0, buffer.Length);
outfile.Close();
Compressing HTTP Output
Besides compressing files, one other very good use of the compression features of the NET Framework
in an ASP.NET application is to implement your ownHttpModuleclass that compresses the HTTP output
of your application This is easier than it might sound, and it will save you precious bandwidth by
com-pressing the data that is sent from your Web server to the browsers that support the HTTP 1.1 Protocol
standard (which most do) The browser can then decompress the data before rendering it
IIS 6 does offer built-in HTTP compression capabilities, and there are several third-party HTTP
com-pression modules available, such as the Blowery Http Comcom-pression Module (www.blowery.org).
Start by creating a Windows Class library project Add a new class to your project called
Compression-Module This class is your compressionHttpModule Listing 25-22 shows the code for creating the class
Listing 25-22: Compressing HTTP output with an HttpModule
VB
Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.Web
Imports System.IO
Imports System.IO.Compression
Namespace Wrox.Demo.Compression
Public Class CompressionModule
Implements IHttpModule
Continued
Trang 10Public Sub Dispose() Implements System.Web.IHttpModule.Dispose
Throw New Exception("The method or operation is not implemented.")
End Sub
Public Sub Init(ByVal context As System.Web.HttpApplication) _
Implements System.Web.IHttpModule.Init
AddHandler context.BeginRequest, AddressOf context_BeginRequest
End Sub
Public Sub context_BeginRequest(ByVal sender As Object, ByVal e As EventArgs)
Dim app As HttpApplication = CType(sender, HttpApplication)
’Get the Accept-Encoding HTTP header from the request
’The requesting browser sends this header which we will use
’ to determine if it supports compression, and if so, what type
’ of compression algorithm it supports
Dim encodings As String = app.Request.Headers.Get("Accept-Encoding")
If (encodings = Nothing) Then
Return
End If
Dim s As Stream = app.Response.Filter
encodings = encodings.ToLower()
If (encodings.Contains("gzip")) Then
app.Response.Filter = New GZipStream(s, CompressionMode.Compress)
app.Response.AppendHeader("Content-Encoding", "gzip")
app.Context.Trace.Warn("GZIP Compression on")
Else
app.Response.Filter = _
New DeflateStream(s, CompressionMode.Compress) app.Response.AppendHeader("Content-Encoding", "deflate")
app.Context.Trace.Warn("Deflate Compression on")
End If
End Sub
End Class
End Namespace
C#
using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.IO;
using System.IO.Compression;
namespace Wrox.Demo.Compression
{
public class CompressionModule : IHttpModule
Continued