Tải bản đầy đủ (.pdf) (10 trang)

Professional ASP.NET 3.5 in C# and Visual Basic Part 122 docx

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (121.88 KB, 10 trang )

Evjen c25.tex V2 - 01/28/2008 3:42pm Page 1170
Chapter 25: File I/O and Streams
FileStream
resources as
Close
does, 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 basic
Stream
model for a variety of data stores, you can use these
same techniques for reading and writing to any of the
Stream
derived classes. Listing 25-15 shows how
you can use the same basic code to write to a
MemoryStream
, and Listing 25-16 demonstrates reading a
Telnet server response using the
NetworkStream
.
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 />’ The WCS Online BBS ()
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 />// The WCS Online BBS ()
System.Net.IPAddress addr = System.Net.IPAddress.Parse("65.182.234.52");
System.Net.IPEndPoint endpoint = new System.Net.IPEndPoint(addr,23);
1170
Evjen c25.tex V2 - 01/28/2008 3:42pm Page 1171
Chapter 25: File I/O and Streams
client.Connect(endpoint);
System.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 a
Stream
object, 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 are
Reader
and
Writer
classes. 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 from
TextReader
.
System.IO
.StringReader

Reads textual information as a stream of in-memory characters. Derived
from
TextReader
.
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 from
TextWriter
.
System.IO
.StringWriter
Writes textual information as a stream of in-memory characters. Derived
from
TextWriter
.
1171
Evjen c25.tex V2 - 01/28/2008 3:42pm Page 1172
Chapter 25: File I/O and Streams
Class 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 e xample.
Listing 25-17 shows you how to use a
StreamReader
to read a
FileStream
.
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 a
StreamReader
, you must pass an existing stream instance as a constructor
parameter.Thereaderusesthisstreamasitsunderlying data source. In this sample, you use the
File
class’s static
Open
method to open a writable
FileStream
for your
StreamWriter

.
Also notice that you no longer have to deal with byte arrays. The
StreamReader
takes care of converting
the data to a type that’s more user-friendly than a byte array. In this case, you are using the
ReadToEnd
method to read the entire stream and convert it to a string. The
StreamReader
provides 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 the
Read
method, to reading the entire file using the
ReadToEnd
method.
Figure 25-12 shows the results of your write when you open the file in Notepad.
1172
Evjen c25.tex V2 - 01/28/2008 3:42pm Page 1173
Chapter 25: File I/O and Streams
Figure 25-12
Now use the
BinaryReader
and
BinaryWriter
classestoreadandwritesomeprimitivetypestoafile.
The
BinaryWriter
writes primitive objects in their native format, so in order to read them using the
BinaryReader
, you must select the appropriate

Read
method. 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
1173
Evjen c25.tex V2 - 01/28/2008 3:42pm Page 1174
Chapter 25: File I/O and Streams
binarywriter.Write(0x12345678);
binarywriter.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 the
BinaryWriter
has written the nonreadable binary
data to the file. Figure 25-13 shows what the content o f the file looks like. The
BinaryReader
provides a
number of different methods for reading various kinds of primitive types from the stream.
In this sample, you use a different
Read
method for each primitive type that you write to the file.
Figure 25-13
Finally, notice that the basic usage of both the
StreamReader
/
StreamWriter
and
BinaryReader
/
BinaryWriter
classes is virtually identical. You can apply the same basic ideas to use any of the reader
or writer classes.
Encodings
The
StreamReader

by 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 the
StreamReader
uses.
StreamReader reader =
new StreamReader(@"C:
\
Wrox
\
text.txt",System.Text.Encoding.Unicode);
1174
Evjen c25.tex V2 - 01/28/2008 3:42pm Page 1175
Chapter 25: File I/O and Streams
The default encoding for t he
StreamWriter
is also UTF-8, and you can override it in the same manner as
the
StreamReader
class.
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 the
File
class. Using these methods, you cause .NET to handle the process of creating the
Stream

and
StreamReader
for 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
1175
Evjen c25.tex V2 - 01/28/2008 3:42pm Page 1176
Chapter 25: File I/O and Streams
System.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 the

GZipStream
or the
DeflateStream
classes.
GZip Compression
Because both new classes are derived from the
Stream
class, using them should be relatively similar
to using the other
Stream
operations you have examined so far in this chapter. Listing 25-20 shows an
example of compressing your text file using the
GZipStream
class.
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];
1176
Evjen c25.tex V2 - 01/28/2008 3:42pm Page 1177
Chapter 25: File I/O and Streams
infile.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 the
GZipStream
constructor requires two parameters, the stream to write the compressed data
to, and the
CompressionMode
enumeration, which tells the class if you want to compress or decompress
data. After the code runs, be sure there is a file called
text.zip
in your Web site directory.
Deflate Compression
The

Compression
namespace also allows to you decompress a file using the
GZip
or
Deflate
methods.
Listing 25-21 shows an example of decompressing a file using the
Deflate
method.
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
1177
Evjen c25.tex V2 - 01/28/2008 3:42pm Page 1178
Chapter 25: File I/O and Streams
System.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 feature s of the .NET Framework
in an ASP.NET application is to implement your own
HttpModule
class 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 d oes offer built-in HTTP compression capabilities, and there are several third-party HTTP com-
pression modules available, such as the Blowery Http Compression 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 compression
HttpModule
. 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
1178
Evjen c25.tex V2 - 01/28/2008 3:42pm Page 1179
Chapter 25: File I/O and Streams
Public 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
1179

×