Accessing Files

IOTA^_^    

Sams Teach Yourself ASP.NET in 21 Days, Second Edition
By Chris Payne
Table of Contents
Day 13.  Reading and Writing Files on the Web Server


The System.IO namespace provides a lot of functionality that you can take advantage of from your ASP.NET pages, including reading and writing files, creating and deleting directories, and examining file and directory attributes. This namespace also allows you to react to events that occur on the file system, such as a directory being deleted or created by another user.

Files, Streams, Readers, and Writers

Before you begin examining the System.IO classes and accessing files, you should learn the differences between files and streams because they are very distinct in ASP.NET.

graphics/newterm_icon.gif

Technically, a file is a collection of data with a name that is located in a distinct place, and is stored for an indefinite period of time. For example, a file exists on your computer's hard drive, has a filename and path, and can be accessed whenever you need it. Think of a file as a box with stuff inside it a tangible object.

graphics/newterm_icon.gif

A stream, on the other hand, is not concerned with filenames, paths, or storage locations. A stream can be used to read and write data from any location, such as a hard disk, a network, or memory. Therefore, a stream is a way to access any data, including files. When you open and read files, you're actually using streams to do so. The Stream class is a base object that many other classes inherit from.

Streams are used for binary access: They read raw data from files as 1s and 0s. This method of access has its place, but in ASP.NET, we're mostly concerned with Unicode access; that is, reading characters and strings as opposed to 1s and 0s.

The .NET Framework provides two other objects for just this purpose: TextReader and TextWriter. I won't talk much about these base objects here, but know that many classes inherit from these two as well. The XmlTextReader and XmlTextWriter from Day 11, "Using XML in ASP.NET," were two. You'll learn a few more today.

Here we have arrived with two separate branches of entities: Stream and its subclasses for binary access; TextReader and TextWriter and their subclasses for Unicode access. When exploring the .NET Framework, you'll be able to tell the difference immediately: Classes and objects that inherit from Stream generally have the word stream in their name (FileStream, MemoryStream, and so on). Classes that inherit from TextReader and TextWriter generally have the word reader or writer in their name (XmlTextReader, BinaryWriter, and so on).

Thankfully, there are classes that can convert between the binary and Unicode data. You'll be examining two important ones for ASP.NET file I/O StreamReader and StreamWriter later today. Figure 13.2 depicts the relationship between all these objects.

Figure 13.2. The relationship between Streams, TextReaders, and TextWriters.

graphics/13fig02.gif

Note

Don't get Streams and streaming confused. Streams allow access to data stores, whereas streaming provides dynamic access to data, piece by piece, when you request it; the former is a noun, the latter is a verb. Streams can be streamed, but don't have to be.


graphics/newterm_icon.gif

The Stream object allows asynchronous access. This means that while you are performing operations on the file, you can continue to execute other code at the same time. For example, if you are writing information into a very large file, and you expect it to take a minute of processing time, you can open the file asynchronously and perform the write operation in the background, while running the code to redirect users around your site.

The opposite of this is synchronous execution. With this mode, you must wait for the code to finish executing before continuing on with something else, which might result in some performance penalties. Figure 13.3 shows the order of operation differences between the two modes. I focus on only synchronous access here because it is easier to use and is more common, but for more information, see the .NET Framework SDK documentation.

Figure 13.3. Asynchronous operation often results in better performance.

graphics/13fig03.gif

Examining Files and Directories

There are four main objects that we will focus on: the File and Directory objects, and the FileInfo and DirectoryInfo objects. The first two objects provide methods to create, modify, and delete files and directories, and the latter two provide properties to examine their attributes. Listing 13.1 shows an example.

Listing 13.1 Viewing File and Directory Information
 1:<%@ Import Namespace="System.IO" %> 2:<script language="VB" runat="server"> 3: 4:   sub Page_Load(Sender as Object, e as EventArgs) 5:      dim f as new FileInfo(Server.MapPath("listing1301.aspx")) 6: 7:      lblMessage.Text = "File information<br>" & _ 8:         "<b>Name: </b>" & f.Name & "<br>" & _ 9:         "<b>Path: </b>" & f.DirectoryName & "<br>" & _ 10:         "<b>Last access time: </b>" & f.LastAccessTime & _ 11:            "<br>" & _ 12:         "<b>Last write time: </b>" & f.LastWriteTime & _ 13:            "<br>" & _ 14:         "<b>Length: </b>" & f.Length & " bytes<p>" 15: 16:      'return parent directory 17:      dim dir as DirectoryInfo = f.Directory 18: 19:      lblMessage.Text += "Directory information<br>" & _ 20:         "<b>Name: </b>" & dir.Name & "<br>" & _ 21:         "<b>Full name: </b>" & dir.FullName & "<br>" & _ 22:         "<b>Last access time: </b>" & dir.LastAccessTime & _ 23:            "<br>" & _ 24:         "<b>Last write time: </b>" & dir.LastWriteTime & _ 25:            "<br>" & _ 26:         "<b>Parent: </b>" & dir.Parent.Name & "<br>" 27: 28:   end sub 29: 30:</script> 31: 32:<html><body> 33:   <asp:label  runat=server/> 34:</body></html> 

graphics/analysis_icon.gif

Save this listing as Listing1301.aspx. On line 1, you import the additional namespace, System.IO. On line 5, you instantiate a new FileInfo object with the file containing the code from this listing (this way you guarantee that the file exists).

Recall from Day 4, "Using ASP.NET Objects with C# and VB.NET," that the Server.MapPath method maps a virtual directory to its physical path. Lines 8 14 list all the properties of this file. Figure 13.4 illustrates the values returned for each property.

Figure 13.4. Viewing file and directory properties.

graphics/13fig04.gif

On line 17, you use the Directory property to return a DirectoryInfo object based on the file's parent directory. Then, on lines 20 26, you display the properties for this directory. Many of the properties of the FileInfo and DirectoryInfo objects are similar.

Caution

If the specified file does not exist, you will receive an error. Use the FileExists method of the File object to determine whether a file exists.

Similarly, use the DirectoryExists method of the Directory object to determine whether a directory is valid.


The File and Directory objects also have an Attributes collection that provides additional information, such as whether the file is read-only or hidden. These attributes are listed in Table 13.1.

Table 13.1. File and Directory Attributes and Values
Attribute Value
Readonly 1
Hidden 2
System 4
Directory 16
Archive 32
Encrypted 64
Normal 128
Temporary 256
SparseFile 512
ReparsePoint 1024
Compressed 2048
Offline 4096
NotContentIndexed 8192

These values are accumulated per file. For example, for the file listing1301.aspx in Listing 13.1, the line

 Response.Write(f.Attributes) 

produces the string "32", which means that this file is archived. To change the attributes for the file, simply sum the values and set the Attributes property. For example, to make the file hidden, compressed, encrypted, and not indexed, use

 f.Attributes = 10306 

Caution

You cannot assign attribute values directly. For instance, this line

 f.Attributes.Hidden = 2 

will result in an error. The Hidden attribute is a constant and cannot be modified. You must change the attributes directly, like so:

 f.Attributes = 2 


These attribute values can be a pain to memorize, so you can use their names instead, separating each attribute with an Or operator (the | operator in C#):

 f.Attributes = FileAttributes.Hidden Or _    FileAttributes.Compressed Or _    FileAttributes.NotContentIndexed 

This code snippet does the same as setting the attribute value to 10306. The Or operator is part of VB.NET's bitwise operators, which allow you to compare bit values. Other operators include And, Not, and Xor. To determine whether a file has a certain attribute set, use the And operator:

 if f.Attributes And FileAttributes.Hidden > 0 then    Response.write("Hidden") end if 

This is great for displaying information on one file or directory. However, what happens when you need to view more information, such as for all the files in a directory? The DirectoryInfo object provides two methods that return collections of files and directories: GetFiles and GetDirectories. Listing 13.2 shows an example of iterating over these collections.

Listing 13.2 Iterating over Files and Directories Within a Directory
 1:    <%@ Import Namespace="System.IO" %> 2:    <script language="C#" runat="server"> 3: 4:       void Page_Load(Object Sender, EventArgs e) { 5:          DirectoryInfo dir = new DirectoryInfo (Server.MapPath("/tyaspnet21days")); 6: 7:          DataGrid1.DataSource = dir.GetFiles("*.*"); 8:          DataGrid1.DataBind(); 9: 10:          DataGrid2.DataSource = dir.GetDirectories(); 11:          DataGrid2.DataBind(); 12: 13:       } 14: 15:    </script> 16: 17:    <html><body> 18:       <b>File information</b><br> 19:       <asp:DataGrid  runat="server" 20:          width="100%" 21:          Font-Name="Arial" 22:          Font-Size="10pt" 23:          AlternatingItemStyle-Backcolor="#cccccc" 24:          AutogenerateColumns="true" /> 25: 26:       <p> 27:       <b>Directory information</b><br> 28:       <asp:DataGrid  runat="server" 29:          width="100%" 30:          Font-Name="Arial" 31:          Font-Size="10pt" 32:          AlternatingItemStyle-Backcolor="#cccccc" 33:          AutogenerateColumns="true" /> 34:    </body></html> 

graphics/analysis_icon.gif

On line 7, you specify GetFiles("*.*") to return all files in the current directory; "*.*" means any string, followed by a period, followed by any string (for example, Listing1301.aspx). Because this method returns a collection, you can easily use a DataGrid to display the items in the way you want. You use GetDirectories on line 10 to return a collection of the directories in the current directory, and likewise, display the information in a DataGrid. Figure 13.5 shows the output of this listing.

Figure 13.5. Looping through the files and directories collection.

graphics/13fig05.gif

You could have also used a for each loop to iterate through the collections, but the DataGrid provides a much easier mechanism for display. To loop through and display all the subfolders and their files, you could use a recursive function.

Let's develop a slightly more useful example. You'll create a file browser that can be used to view the contents of your hard drive, much like Windows Explorer. This page should allow users to view files by navigating through directories (as in Windows), and also allow users to enter a directory name manually for quicker navigation. Listing 13.3 shows the ASP.NET code for this page.

Listing 13.3 Building a File Navigation System Listing1303.aspx
  1:<%@ Import Namespace="System.IO" %>  2:<script language="VB" runat="server">  3:   private dir as DirectoryInfo  4:   private f as FileInfo  5:   private strDir as string  6:  7:   sub Page_Load(Sender as Object, e as EventArgs)  8:      if not Page.IsPostBack then  9:         strDir = Request.Params("dir") 10: 11:         if strDir = "" then 12:            strDir = "c:\" 13:         end if 14: 15:         tbDir.Text = strDir 16:         dir = new DirectoryInfo(strDir) 17:         ListFiles() 18:      end if 19:   end sub 20: 21:   sub tbDir_Handle(Sender as Object, e as EventArgs) 22:      strDir = Sender.Text 23:      if Directory.Exists(strDir) then 24:         dir = new DirectoryInfo(strDir) 25:         ListFiles() 26:      else 27:         lblMessage.Text = "Invalid directory" 28:      end if 29:   end sub 30: 31:   sub ListFiles() 32:      dim hl as HyperLink 33:      dim d as DirectoryInfo 34:      if not dir.Root.FullName = dir.FullName then 35:         hl = new HyperLink 36:         hl.Text = ".." 37:         hl.NavigateURL = "listing1303.aspx?dir=" & _ 38:            Server.URLEncode(dir.Parent.FullName) 39:         Panel1.Controls.Add(hl) 40: 41:         Panel1.Controls.Add(new LiteralControl("<br>")) 42:      end if 43: 44:      for each d in dir.GetDirectories 45:         hl = new Hyperlink 46:         hl.Text = d.Name 47:         hl.NavigateURL = "listing1303.aspx?dir=" & _ 48:            Server.URLEncode(d.FullName) 49:         Panel1.Controls.Add(hl) 50: 51:         Panel1.Controls.Add(new LiteralControl("<br>")) 52:      next 53: 54:      for each f in dir.GetFiles("*.*") 55:         lblMessage.Text += f.Name & "<br>" 56:      next 57:   end sub 58:</script> 

graphics/analysis_icon.gif

Save this file as listing1303.aspx. The first time the user visits this page, he will see the directory listing for the root drive (C:\, in this case). The Request parameter dir is checked on line 9 its value is used to find out what the current directory should be. If this parameter is blank (as it should be on first viewing), you use the default directory C:\. You then create a new DirectoryInfo object for this directory on line 16, set a text box's Text property to the same directory on line 15 (for UI purposes), and call the ListFiles method on line 17.

The ListFiles function, beginning on line 31, iterates over the collection of directories within the current directory, as you have done previously. First, however, you perform a check to determine whether you're at the root directory on line 34. If not, you want to display the .. marker, which allows users to move up one directory. You create a new Hyperlink control to display the .., and append the path of the current directory's parent folder on the querystring. When the user clicks on this link, this same page is brought up, with an additional querystring parameter named dir that specifies the new directory path the next highest directory, in this case. The Page Load event uses this parameter to create a new directory object. On line 41, you create a new LiteralControl that introduces a line break after the .. marker.

You do a similar task for each directory: You create a Hyperlink control that directs the user back to this page. The Hyperlink displays the short name of the directory (shown on line 46), and you append the full name to the querystring (shown on line 47). This page uses this parameter to display a new directory. On line 51, you again add a LiteralControl to provide a line break between directory links.

On lines 54 56, you iterate over the files in the directory and add their names to a label control. Before you examine the final method, tbDir_Handle, take a look at the UI portion of this page in Listing 13.4.

Listing 13.4 UI Portion of the Directory Listing Page Listing1303.aspx
  1:<html><body>  2:   <form runat="server">  3:      <b>Directory:</b>  4:      <asp:Textbox  runat="server"  5:         OnTextChanged="tbDir_Handle"  6:         AutoPostBack=true /><p>  7:      <asp:Panel  runat="server"  8:         MaintainState="true" />  9:      <asp:label  runat=server 10:         maintainstate=false /> 11:   </form> 12:</body></html> 

graphics/analysis_icon.gif

There are three elements on this page: a TextBox control that displays the current directory path; a Panel that holds the Hyperlink controls; and a Label that holds the filenames and any miscellaneous messages. When the text in the text box has changed (presumably when the user changes a directory manually), the tbDir_Handle event takes control.

This handler, as shown on lines 21 29 of Listing 13.3, retrieves the text from the text box and uses it to set the new directory. Note the if statement on line 21. Any time you allow the user to enter information manually, you want to make sure that it is valid information. The DirectoryExists method is used here to determine whether the specified path is an existing directory. If the directory isn't valid, an error message is sent to the user. This is a very important check, especially with this type of application.

Finally, if the directory is valid, the ListFiles method is called again to list the directories. Figure 13.6 shows a sample output.

Figure 13.6. A sample directory listing using your directory browsing application.

graphics/13fig06.gif

There are two items about this application I haven't yet discussed. The first is the use of Server.URLEncode. Every time you create a Hyperlink and specify a querystring, Server.URLEncode is used to ensure that any special characters are converted to strings that won't mess up the URL. For example, if the path name were c:\Program Files\temp.txt, you might receive an error when dealing with the space between Program and Files. Using Server.URLEncode replaces this string with

 c%3a%5cprogram+files%5ctemp.txt 

All offending characters are replaced with other characters that HTML understands as substitutes.

The second item I haven't discussed is the different methods of calling this page. In the Page_Load event, you check to make sure that the page wasn't just posted back on itself. If it wasn't, it means that the user has changed the current directory by clicking on a Hyperlink control (which doesn't post a form, it only redirects), and you want to use the Page_Load event handler to list the directories and files. If the page was posted back on itself, you want to use the tbDir_Handle method to list the directories and files. The check for postback is very important: without it, the directories might be listed twice on the page.

Opening Files

There are several different methods to open a file with ASP.NET depending on your circumstances. As I discussed earlier, ASP.NET allows you to open files for both binary and Unicode access. Binary access allows you to read the bits (ones and zeroes) that make up a computer file directly. Unicode is a scheme that translates these bits into something we can read, such as letters and numbers. Because binary access isn't that important for your needs, we'll concentrate on the Unicode methods.

Using the File Object

One method to open files is by using the File object. After you have instantiated the object with a file, you can use several different methods to open the file, depending on what you plan to do with the data. Table 13.2 summarizes these methods.

Table 13.2. The File Object's Open Methods
Method Description
Open Opens a file with specified privileges and returns a Stream object.
OpenRead() Returns a read-only stream for the file.
OpenText() Returns a StreamReader from an existing file.
OpenWrite() Returns a read-write Stream.

There are several things to know about these methods. First, let's examine the types of privileges available.

The Open method takes three parameters: FileMode, FileAccess, and FileShare, in that order. The FileMode privilege tells the operating system how to open the file; for example, whether an existing file should be overwritten or appended to. Table 13.3 summarizes the modes available.

Table 13.3. FileMode Values
Mode Description
Append Opens the file if it exists, and moves to the end of the file. Or, if the file doesn't exist, creates a new one. This mode can be used only with the Write file access privilege (you'll get to that in a moment).
Create Creates a new file or overwrites an existing one.
CreateNew Creates a new file.
Open Opens an existing file.
OpenOrCreate Opens a file if it exists; otherwise, creates a new one.
Truncate Opens an existing file, and then truncates it so that its size is zero bytes, effectively erasing its contents.

FileAccess specifies the access privileges on a file. The possible values are Read, ReadWrite, and Write, which create read-only, read-write, and write-only access, respectively.

Finally, FileShare specifies what should happen if two processes try to access the file at the same time; for instance, if two visitors come to your Web site and try to change a file's contents at the same time. The values specified affect the second process that accesses the file. The values are the same as those for FileAccess, with one additional value: None, which specifies that another process cannot access the file at the same time as another process.

One thing you might have noticed is that these methods of the File class, with the exception of OpenText, all return Stream objects, which allow only binary access not ideal for us. I'll discuss how to get around that when we talk about reading files.

The following code shows an example of using the File object to open a file.

 'create a File object and StreamReader dim objFile as new File(Server.MapPath("log.txt")) dim objReader as StreamReader 'open the file objReader = objFile.OpenText 'do some stuff 'close the StreamReader objReader.close 

Or, you could use the Open method:

 dim objFile as new File(Server.MapPath("log.txt")) dim objStream as Stream objStream = objFile.Open(FileMode.OpenOrCreate, FileAccess.Read) 
Using the FileStream Object

The FileStream object allows you to create a Stream to access a file. One benefit of using the FileStream object is that you do not have to use a File object first. However, you must make sure that the file you are accessing exists. This was not necessary when opening files with the File object because if you successfully created a File object, you know that the file does exist. The following code demonstrates how to open a file:

 dim fs as new FileStream(Server.MapPath("log.txt"), _    FileMode.OpenOrCreate) 

This opens a file with the OpenOrCreate instruction. The FileStream object uses the same parameters as the File.Open method, with the addition of the path to the file.

The FileStream object also provides a method, Seek, that allows you to move to any position in the stream (such as to the end or beginning). The syntax for this method is as follows:

 Seek(offset, origin) 

The offset parameter specifies how far from the origin you want to move. origin can be one of the following SeekOrigin enumeration values: SeekOrigin.Begin, which specifies the beginning of the stream; SeekOrigin.Current, which specifies from the current position; or SeekOrigin.End, which specifies the end of the file. For example, the following code snippet moves to the beginning and end of a file:

 'Seek to the beginning of a file objFile.Seek(0, SeekOrigin.Begin) 'Seek to the end of a file objFile.Seek(0, SeekOrigin.End) 

Reading Files

Now that you have an open file, you are ready to read its content. For ASP.NET, this is done mainly with the StreamReader object. As discussed earlier, this object converts from binary to Unicode, which gives you the characters and strings you need to use in your pages. Instantiating a StreamReader object is simple:

 dim objReader as new StreamReader(object) 

The object parameter can be either a Stream object (such as the FileStream created in the last snippet) or a path to a specific file. Let's create a simple file to use for our examples. Place the following in log.txt text file in the /TYASPNET21Days/Day13 directory:

 The Quick Foxes Jumped Over The Lazy Brown Dog 

StreamReader provides several methods to read characters from a file. The first, Read, returns a single character from the stream as an integer, and moves ahead by one. For example:

 dim f as new File(Server.MapPath("log.txt")) objReader = f.OpenText Response.Write(objReader.Read & "<br>") objReader.Close 

The preceding code would return 84, which is the ASCII representation of the uppercase letter T. Calling Read again would return 104, which is the ASCII representation of the lowercase letter h, and so on. These numbers aren't very useful as is, so you should convert them to actual Unicode characters with the Chr method of the Strings class:

 Response.Write(Strings.Chr(objReader.Read) & "<br>") 

This would return T for the first call, h for the second, and so on.

Reading single characters at a time might be a bit tedious, so the StreamReader provides two other methods that return more characters: ReadLine, which reads characters until it reaches a line break, and ReadToEnd, which reads until it reaches the end of the stream. For example:

 objReader = new StreamReader(Server.MapPath("log.txt")) Response.Write(objReader.ReadToEnd) objReader.Close 

would return

 The Quick Foxes Jumped Over The Lazy Brown Dog 

What happened to the line breaks? If you view the HTML source of this output, you'll see that the line breaks are still there. Unfortunately, HTML doesn't interpret actual line breaks as HTML breaks (that is, as <br>). You can use the ReadLine method to insert those:

 Response.Write(objReader.ReadLine & "<br>") 

This method, however, only reads one line at a time, so you'll have to use a loop to iterate through the entire file. If you hit the end of the file using ReadLine or Read and you try to read the next character, you'll receive an error. Luckily, the StreamReader object provides a method, Peek, that helps you avoid this.

The Peek method reads the next character, but doesn't actually return it. This allows you a sneak peek of the next character in the stream. If that next character happens to be the end of the stream, the Peek method returns -1. Now you can read through the stream without any worries:

 dim objReader as new StreamReader(Server.MapPath("log.txt")) while objReader.Peek() > -1    Response.Write(objReader.ReadLine & "<br>") end while objReader.Close 

Figure 13.7 shows the output of this code.

Figure 13.7. Reading a stream with the ReadLine method.

graphics/13fig07.gif

Caution

Because the Peek method does not actually read from the stream, it does not advance the StreamReader. Make sure to use a method of the StreamReader that advances the position, or you'll end up with an infinite loop. For instance:

 while objReader.Peek() > -1    Response.Write("<br>") end while 

would result in an infinite loop because the position in the stream is never advanced.


The Read method can also be used to return a specified number of characters from a stream. The syntax for this method is

 objReader.Read(char(), start, count) 

This method reads count number of characters from the stream, beginning at the position indicated by start, and places the output into the array of Chars, char(). For example:

 objReader = new StreamReader(Server.MapPath("log.txt")) dim arrString() as Char = new Char(10) objReader.Read(arrString, 0, 10) for i = 0 to Ubound(arrString) - 1    Response.Write(arrString(i)) next objReader.Close 

On line 2, you create an array of Chars, arrString. On line 4, you use the Read method to read 10 characters from the stream, starting at position 0 (the beginning of the stream), and place them into arrString. This output returns:

 The Quick 

Eight characters, plus one space (k is the end).

Imagine that for educational purposes, you want to show the source code for one of your ASP.NET Web pages to a Web site visitor; for instance, to teach a particular method. When the visitor tries to view the source of an ASP.NET file from the browser, he'll see only HTML all ASP.NET commands have been processed and removed. Thus, it is up to you to show your visitor the file before it is processed. You can do this with the System.IO classes, and Listing 13.5 shows how.

Listing 13.5 Viewing ASP.NET Source Code in the Browser
  1:<%@ Import Namespace="System.IO" %>  2:<script language="VB" runat="server">  3:   sub Page_Load(Sender as Object, e as EventArgs)  4:      dim fs as new FileStream(Server.MapPath _  5:         ("listing1305.aspx"), FileMode.Open, _  6:         FileAccess.Read)  7:      dim objReader as new StreamReader(fs)  8:  9:      lblMessage.Text = "<pre>" 10:      while objReader.Peek() > -1 11:         lblMessage.Text += Server.HTMLEncode _ 12:            (objReader.ReadLine) & "<br>" 13:      end while 14:      objReader.Close 15:      fs.close 16:      lblMessage.Text += "</pre>" 17:   end sub 18:</script> 19: 20:<html><body> 21:   <form runat="server"> 22:       <asp:label  runat=server /> 23:   </form> 24:</body></html> 

graphics/analysis_icon.gif

In the Page_Load event handler, you create a new FileStream based on the file you want to view. On line 7, you create a StreamReader to read that stream's content. The <pre> tag allows the formatting to remain the same as it is in the source file. You then use the Peek and ReadLine methods to loop through the lines of the file, making sure to call Server.HTMLEncode so that the HTML tags are not interpreted. Finally, you close your StreamReader and FileStream objects, and write the closing </pre> tag in the label. Figure 13.8 shows the output for this listing.

Figure 13.8. Viewing ASP.NET source code from the browser.

graphics/13fig08.gif

Writing Files

The StreamWriter object allows you to write data to streams. The syntax for a StreamWriter is very simple. As with the StreamReader object, StreamWriter can be built around a Stream object or from a path that specifies a file.

 dim objWriter as new StreamWriter(FileStream Or Path, Append) 

The Append parameter is a Boolean that specifies whether a file should be appended to. If this value is false, an existing file will be overwritten. If the file does not exist, it will be created. If Append is true, anything you write to the file will be added to the end of what is already there.

The StreamWriter object provides two methods to write data: Write and WriteLine. For example:

 dim objWriter as new StreamWriter(Server.MapPath ("log.txt"), true) objWriter.WriteLine("And I care because?") objWriter.Write("because I say so.") objWriter.Close 

Line 1 creates a new StreamWriter on the log.txt file, for appending. Lines 4 and 5 use the two different methods to write strings to the file, and you close the writer on line 7. After executing this code, the log.txt should now look like:

 The Quick Foxes Jumped Over The Lazy Brown DogAnd I care because? because I say so. 

There is a line break after the call to WriteLine. However, there is no line break between the new text we added and the old. To introduce a line break, simply call the WriteLine method without any parameters:

 objWriter.WriteLine() 

The StreamWriter object provides buffered output. Recall the discussion about buffered page output on Day 4. By default, when you write data using either the Write or WriteLine method, StreamWriter buffers the output before sending it to the stream. You can set the AutoFlush property to true to force StreamWriter to flush its buffer after every call to Write or WriteLine.

You can also call the Flush method to flush the buffer manually. Setting AutoFlush to false will result in slightly better performance. An example of a situation in which you would want to set AutoFlush to true is if your users expect immediate feedback; for example, if you are adding a large amount of content to a file, and want the user to be able to see the changes in the file before processing is finished.

Other File and Directory Operations

Both the File and Directory objects provide methods for copying, creating, moving, and deleting files and directories. These methods are straightforward. Table 13.4 summarizes them. The methods not otherwise specified apply to both objects.

Table 13.4. Miscellaneous File and Directory Methods
Method Description
Directory.CreateDirectory Creates a directory with the specified path. If a nonexistent directory is specified in any part of the path, ASP.NET will generate an error.
Directory.Delete Deletes a directory. Recursive is a Boolean value that specifies whether to delete subdirectories and files as well.
File.Copy Copies an existing file to a new file. Overwrite specifies whether any existing files should be overwritten.
File.Create Creates a file in the specified path.
File.CreateText Creates a StreamWriter object that writes to a new text file.
File.Delete Deletes a file.
FileSystemInfo.Extension This function returns a file extension.
Move Moves the specified file or directory from the oldpath to the newpath.

To rename a file or path, you can use the File.Move method. You can also use Copy to rename a file, but remember to delete the old filename after you've made the copy.

Summary of File Objects

With so many ways to access the file system in ASP.NET, choosing which object to use and when may be confusing. Table 13.5 summarizes the objects and their uses.

Table 13.5. Summary of System.IO Objects and Enumerations
Object When to Use
BinaryReader and BinaryWriter Reading and writing binary data from streams (for example, data types and objects)
Directory Creating, deleting, and manipulating directories
File Creating, deleting, and manipulating files on disk
FileInfo and DirectoryInfo Viewing and manipulating properties of files and directories
FileAttributes and DirectoryAttributes Determining file and directory attributes
FileMode, FileAccess, and FileShare Specifying the privileges and behavior for opening files
FileStream Accessing files, with the ability to seek randomly to any point in the file
MemoryStream Accessing streams in memory
SeekOrigin Specifying an origin for the FileStream.Seek method
StreamReader and StreamWriter Reading and writing bytes to and from streams
  Reading and writing Unicode characters to and from streams
StringReader and StringWriter Reading and writing to and from strings; provides the same functionality as StreamReader and StreamWriter


    IOTA^_^    
    Top


    Sams Teach Yourself ASP. NET in 21 Days
    Sams Teach Yourself ASP.NET in 21 Days (2nd Edition)
    ISBN: 0672324458
    EAN: 2147483647
    Year: 2003
    Pages: 307
    Authors: Chris Payne

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net