1. Trang chủ
  2. » Công Nghệ Thông Tin

Professional ASP.NET 1.0 Special Edition- P30 potx

40 209 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 40
Dung lượng 466,41 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

If successful, this method returns a StreamReader object that can be used to read characters not bytes from the file.. Once we've written code to read or write data from a backing store

Trang 1

Do While Not name Is Nothing

Here we use the File.OpenText method to open up the names.txt file If successful, this method returns a

StreamReader object that can be used to read characters (not bytes) from the file Our code uses the ReadLine method, which reads all characters up to the next carriage return line feed Although this method reads the carriage return line feeds from the stream, they are not returned as part of the return string When the end of the file is reached, a Null string

is returned We check for this and use it to terminate our while loop Calling the Close method closes the file

To ensure that our code remains scalable we should always close files as soon as possible

The following code shows how we can create a new text file and write a few lines to it:

<%@ Page Language="VB" %><%@ Import Namespace="System.IO" %><%

Dim books As StreamWriter

books = File.CreateText(Server.MapPath("books.txt"))

books.WriteLine("Professional ASP.NET")

books.WriteLine("Professional C#")

books.Close()%>

Trang 2

Here we use the File.CreateText method to create a new file This method returns a StreamWriter object that we

can use to write data to the file Then we call the WriteLine method of the object (which is inherited from the base class,

TextWriter) and output the names of the two books Finally, we call the Close method to close the connection to the

file

Once we've written code to read or write data from a backing store (such as the file system) using the StreamReader or

StreamWriter classes we can easily read and write character data from other backing stores (such as memory buffers

or network connections) using the same classes This consistency makes working with streams of data easy

The main role of the StreamReader and StreamWriter classes is essentially to convert bytes of data into characters

Different character encoding types, such as Unicode, ASCII, or UTF-8, use different byte sequences to represent their

characters, but no matter where bytes are read from, or written to, these same translations are performed, so it makes

sense to always use the same classes for this purpose To support this, the classes read and write bytes of data using a

Stream class, as shown in the following diagram:

This generic model is very powerful To support reading character data from different backing stores, all we require is a

stream object for each backing store Each of these stream objects inherits from the Stream class and overrides several

abstract methods that can be used to read and write bytes of data; provide the current position in the stream as well as

change it; determine the length of the stream; and expose the capabilities of the backing store (for example, whether it

is read-only, or write-only)

Trang 3

The following diagram shows how reading and writing from the file system, network sockets, and memory buffers is

supported by this model:

The FileStream, NetworkStream, and MemoryStream classes all derive from the Stream class

The StreamReader and StreamWriter classes contain a reference to the stream object they use to access the

associated backing store This reference is held in the BaseStream property (defined as type Stream) If we had a

reference to a StreamReader, and we knew the backing store was actually a FileStream, we could use this property

to get a reference to the original FileStream object:

Dim myfile As StreamReader

Dim backingStore As FileStream

' assuming backingStore and myfile are already initialized

Trang 4

backingStore = CType(myfile.BaseStream,FileStream)

backingStore.Seek(0,SeekOrigin.Begin)

The capabilities of a stream object will depend on the backing data store For example, if we're using a StreamReader

to read data from a socket (for example, a web page over HTTP), we cannot change the position of the stream since we cannot push data back into a socket once it has been read To determine the capability of a backing store the Stream class has a number of read-only properties:

ƒ CanRead- determines if data can be read from a stream If this property returns true, the Read method can be used to read a specified number of bytes from the Stream into a byte array at a given offset, or the ReadByte method can be used to read a single byte

ƒ CanWrite- determines if data can be written to a stream If this property returns true, the Write method can

be used to write a specified number of bytes from a byte array to the Stream, or the WriteByte method can

be used to write a single byte

ƒ CanSeek- indicates if a stream supports random access If it does, the Position property of the stream class can be used to set the stream position Alternatively, the Seek method can be used to set a relative position from the start of the stream, the end of the stream, or the current position of the stream The SetLength method can also be called to change the size of the underlying backing data store object

Consider the Stream in NET to be the replacement of the IStream interface in COM In future versions of NET the Stream object will automatically expose the IStream interface through COM interop

FileStream

The FileStream class provides all of the functionality we would expect to have available when we are reading and writing data to files It derives from the Stream class, so it inherits all of the properties and methods we've just discussed The FileStream class has the following constructors that we can use to open and create files in various modes:

path as string, mode as FileMode

Specifies a path/file and how we want to work with it FileMode is an enumeration that defines how we want to work with a file, and what actions we want to take if it already exists We'll cover the values of FileMode shortly

path as string,mode as FileMode,access as

FileAccess

As for the previous constructor, but also allows us to specify if we want permissions to read, write, or read and write from the stream Values for FileAccess are Read, ReadWrite, and Write The default is ReadWrite

path as string,mode as FileMode,access as As with the previous constructor, but also allows us to specify what

Trang 5

FileAccess,share as FileShare access other people will have to the file while we're working with it

Values for FileShare are None, Read, ReadWrite, Write, and Inheritable The default is None (that is, nobody else can access the file)

path as string,mode as FileMode,access as

FileAccess,share as

FileShare,bufferSize as Integer

As with the previous constructor, but also allows us to specify the size

of the internal buffer used to reduce the number of calls to the underlying operation system The default value is 4KB We should not change the size of this buffer unless we have good reasons to do so path as string,mode as FileMode,access as

The following code shows how we can create a new text file using the FileStream class:

<%@ Page Language="VB" %><%@ Import Namespace="System.IO" %>

ƒ Append- opens the specified file and seeks to the end of the stream If a file does not exist it is created.

ƒ CreateNew- creates the specified file If the file already exists, an IOException is thrown

ƒ Create- creates the specified file, truncating the file content if it already exists

ƒ Open- opens the specified file If the file doesn't exist, a FileNotFound exception is thrown

ƒ OpenToCreate- opens the specified file, and creates it if it doesn't already exist

ƒ Truncate- opens the specified file and clears the existing contents If the file doesn't exist, a FileNotFound exception is thrown

Trang 6

Once a file is opened and we have a FileStream object, we can create a reader or writer object to work with the file's contents The following code shows how we can write a few lines of text to a file using the StreamWriter class:

<%@ Page Language="VB" %><%@ Import Namespace="System.IO" %>

The lifetime of the writer is tied to that of the stream When the writer is closed, the stream is also closed by the writer, which is why we call sw.Close in this code rather than fs.Close

When a stream is closed (assuming the writer didn't close it) the writer can no longer write to the stream The same is true for reader objects Any attempt to perform an operation on a closed stream will result in an exception

The following code shows how we can open an existing file using the FileStream class and read lines of text from it using the StreamReader class:

<%@ Page Language="VB" %><%@ Import Namespace="System.IO" %>

Trang 7

<%

Dim fs As FileStream

Dim sr As StreamReader

Dim line As String

fs = New FileStream("MyFile.Txt", FileMode.Open)

The following code demonstrates how we can use the MemoryStream class to create a byte array containing the text

"Professional ASP.NET" Although something of an esoteric example, it demonstrates how we can use a stream

Trang 8

writer to fill the memory stream with some text, and then create a byte array containing that text:

<%@ Page Language="VB" %><%@ Import Namespace="System.IO" %><%

Dim memstream As MemoryStream

Dim writer As StreamWriter

Dim array() As Byte

memstream = New MemoryStream()

writer = New StreamWriter(memstream)

In our code we use the ToArray method of MemoryStream to convert the memory buffer into a byte array We have to explicitly call the Flush method before calling this method, since the amount of data written to the stream using the Write method is less than 1KB If we didn't call Flush first, we'd simply end up with an empty array, as no data would have actually been written to the memory stream In this case we have to call Flush, since calling the ToArray method after calling the Close method would also result in an empty array, as the memory stream releases its resources (memory) when the Close method is called

The Capacity property can be used to determine the amount of data a memory stream can hold before it will need to reallocate its buffer We can set this property to increase or shrink the size of the memory buffer However, we cannot set the capacity of the memory stream to be less than the current length of the memory stream, as the length reflects how much data has already been written to the memory stream To determine how much data is currently in a memory stream

we can use the read-only Length property

Trang 9

The MemoryStream class automatically manages its own capacity expansion When a memory stream is full it doubles in size, allocating a new buffer and copying the old data across

When using classes such as StreamWriter to populate a memory stream, the memory stream's Length property will not be accurate until the stream writer's Flush method is called (because of the buffering it performs)

TextReader and TextWriter

The StreamReader class derives from the abstract TextReader class This class defines the base methods that are useful to applications that need to read character data It does not define any methods for opening or connecting to an underlying data source (backing store), those are provided by derived classes such as StringReader and

StreamReader

The TextReader class has the following methods:

Method

Close None Closes the underlying backing store connection and dispose of any held resources Read None Reads the next character from the input stream

Read Char array,

is, the method will not return) until data is available

Table continued on following page

Method Name Parameters Description

ReadLine None Returns a string containing the next line of characters

ReadToEnd None Reads all of the remaining content from the input stream into a string We should not use

this method for large streams, as it can consume a lot of memory

Synchronized TextReader Accepts a TextReader object as input and returns a thread-safe wrapper This is a static

method

One of the reasons the TextReader class exists is so that non-stream-oriented backing stores, such as a string, can have an interface consistent with streams It provides a mechanism by which classes can expose or consume a text stream without having to be aware of where the underlying data stream is For example, the following code shows how a function can output the data read from a text-oriented input stream using an ASP.NET page (written using C#):

<script runat="server">

Trang 10

protected void WriteContentsToResponse(TextReader r)

The StringReader class derives from TextReader in order to provide a way of accessing the contents of a string in a text-stream-oriented way The StreamReader class extends TextReader to provide an implementation that makes it easy to read text data from a file We could derive our own classes from TextReader to provide an implementation that makes it easy to read from our internal data source This same model is used for the TextWriter

The StreamWriter class derives from the abstract TextWriter class StreamWriter defines methods for writing character data It also provides many overloaded methods for converting primitive types like bool and integer into character data:

Trang 11

Method Name Parameters Description

Close None Closes the underlying backing store connection and disposes of any resources that are

held

Flush None Flushes any buffered data to the underlying backing store

Synchronized TextWriter Accepts a TextWriter object as input and returns a thread safe wrapper This is a

myfile.WriteLine("My name is {0}", "Richard")

myfile.WriteLine("My name is {0} {1}", "Richard", "James")

myfile.WriteLine("My name is {0} {1} {2}", "Richard", "James", "Anderson")

Dim authors(5) as Object

authors(0) = "Alex"

authors(1) = "Dave"

Trang 12

authors(2) = "Rich"

authors(3) = "Brian"

authors(4) = "Karli" authors(5) = "Rob"

myfile.WriteLine( "Authors:{0},{1},{2},{3},{4},{5}", authors)

myfile.Close()

%>

The contents of the authors.txt file created by this code is:

My name is RichardMy name is Richard JamesMy name is Richard James

AndersonAuthors:Alex,Dave,Rich,Brian,Karli,Rob

StringReader and StringWriter

The StringReader derives from the TextReader class and uses a string as the underlying input stream The string to read from is passed in as a parameter to the constructor

The StringWriter class derives from the TextWriter class and uses a string as the underlying output stream For reasons of efficiency, this underlying string is actually built using a string builder We can optionally pass in your own StringBuilder object as a constructor parameter if we want to add data to existing strings

The following code shows how to build a multi-line string using the StringWriter class:

<%@ Page Language="VB" %><%@ Import Namespace="System.IO" %>

<html>

<body>

<%

Trang 13

Dim sw As StringWriter = New StringWriter()

Reading and Writing Binary Data

Trang 14

When we are working with streams of binary data we often need to read and write primitive types To achieve this we can use the BinaryReader and BinaryWriter classes The following C# code demonstrates how we can use a

BinaryWriter with a FileStream to write a few primitive types to a file:

Trang 16

The following VB NET code shows how we can specify a default encoding of Unicode to use to read from a file:

Dim Reader As StreamReader

Reader = new StreamReader("somefile.txt", System.Encoding.Text.Unicode);

The default encoding for StreamWriter is also UTF-8, and we can override it in the same manner as the StreamReader class For example, the following C# code creates a file using each supported encoding:

Trang 17

char HiChar;

HiChar = (char) 0xaaaa;

stream = new StreamWriter(Server.MapPath("myfile.utf8"), false,

Trang 18

is the preferred encoding since it typically requires less space than Unicode (17 bytes compared to 26 bytes in this example) and is the standard encoding for web technologies such as XML and HTML

BufferedStream

The BufferedStream class reads and writes data to another stream through an internal buffer, the size of which can be specified in the constructor This class is designed to be composed with other stream classes that do not have internal buffers, enabling us to reduce potentially expensive calls by reading large chunks of data and buffering it

The BufferedStream class should not be used with the FileStream or MemoryStream classes because they already buffer their own data

Copying Between Streams

One of the functions of the stream object not included in version 1.0 of NET is the ability to write the content of one stream into another Here is some C# code that shows how it can be implemented:

public static long Pump(Stream input, Stream output)

{ if (input == null)

{ throw new ArgumentNullException("input");

Trang 19

} if (output == null)

{

throw new ArgumentNullException("output");

} const int count = 4096; byte[] bytes = new byte[count]; int numBytes; long totalBytes = 0;

while((numBytes = input.Read(bytes, 0, count)) > 0)

{ output.Write(bytes, 0, numBytes); totalBytes += numBytes; }

return totalBytes;}

This code uses a 4KB buffer to read data from the input stream and write it to the output stream If the copy is successful the total number of bytes copied is returned The method throws an ArgumentNullException if the input parameters are invalid

Always Call Close(), and Watch for Exceptions!

In the non-deterministic world of NET we should always make sure that we call the Close method on our streams If we don't call Close, the time at which the buffered contents of a stream will be written to the underlying backing store is not predictable (due to the way the CLR garbage collector works) Furthermore, since garbage collection does not guarantee the order in which objects are finalized, we may also find our data is not written correctly and may be corrupted For example, it is possible for a stream to be closed before a writer object has flushed its data

Because of this non-deterministic behavior, we should also always add exception handling to our code when using streams There is no performance overhead at run-time for doing this in cases when exceptions are not thrown, and by putting our stream cleanup code in the finally section of the exception handler, we can ensure resources aren't held for an unpredictable amount of time (in the unlikely case that error conditions do arise)

For C# code it's worth considering the using statement, which can be used to automatically close a stream when it goes out of scope, even if an exception is thrown Here's a simple example of the using statement in action:

<%@ Page Language="C#" %>

Trang 20

ASP.NET and Streams

The ASP.NET page framework allows us to read and write content to a page using a stream:

ƒ The Page.Response.Output property returns a TextWriter than can be used to write text content into the output stream of a page

ƒ The Page.Response.OutputStream property returns a Stream object that can be used to write bytes to the output stream of a page

ƒ The Page.Request.InputStream property returns a Stream object that can be used to read bytes of data from a posted request

If content, such as an XML file, was posted to an ASP.NET page, the following VB NET shows how we could read and display the data using the Page.Request.InputStream property:

<%@ Page Language="VB" %><%@ Import Namespace="System.IO" %>

Ngày đăng: 03/07/2014, 07:20

TỪ KHÓA LIÊN QUAN