Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 140 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
140
Dung lượng
4,55 MB
Nội dung
FileInfo f3 = new FileInfo(@"C:\Test3.dat"); using(FileStream readOnlyStream = f3.OpenRead()) { // Use the FileStream object } // Now get a FileStream object with write-only permissions. FileInfo f4 = new FileInfo(@"C:\Test4.dat"); using(FileStream writeOnlyStream = f4.OpenWrite()) { // Use the FileStream object } } The FileInfo.OpenText() Method Another open-centric member of the FileInfo type is OpenText(). Unlike Create(), Open(), OpenRead(), and OpenWrite(), the OpenText() method returns an instance of the StreamReader type, rather than a FileStream type. Assuming you have a file named boot.ini on your C drive, the follow- ing would be one manner to gain access to its contents: static void Main(string[] args) { // Get a StreamReader object. FileInfo f5 = new FileInfo(@"C:\boot.ini"); using(StreamReader sreader = f5. OpenText()) { // Use the StreamReader object } } As you will see shortly, the StreamReader type provides a way to read character data from the underlying file. The FileInfo.CreateText() and FileInfo.AppendText() Methods The final two methods of interest at this point are CreateText() and AppendText(), both of which return a StreamWriter reference, as shown here: static void Main(string[] args) { FileInfo f6 = new FileInfo(@"C:\Test5.txt"); using(StreamWriter swriter = f6.CreateText()) { // Use the StreamWriter object } FileInfo f7 = new FileInfo(@"C:\FinalTest.txt"); using(StreamWriter swriterAppend = f7.AppendText()) { // Use the StreamWriter object } } As you would guess, the StreamWriter type provides a way to write character data to the underlying file. CHAPTER 20 ■ FILE I/O AND ISOLATED STORAGE672 8849CH20.qxd 10/17/07 5:58 PM Page 672 www.free-ebooks-download.org Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com Working with the File Type The File type provides functionality almost identical to that of the FileInfo type, using a number of static members. Like FileInfo, File supplies AppendText(), Create(), CreateText(), Open(), OpenRead(), OpenWrite(), and OpenText() methods. In fact, in many cases, the File and FileInfo types may be used interchangeably. To illustrate, each of the previous FileStream examples can be simplified by using the File type instead: static void Main(string[] args) { // Obtain FileStream object via File.Create(). using(FileStream fs = File.Create(@"C:\Test.dat")) { } // Obtain FileStream object via File.Open(). using(FileStream fs2 = File.Open(@"C:\Test2.dat", FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None)) { } // Get a FileStream object with read-only permissions. using(FileStream readOnlyStream = File.OpenRead(@"Test3.dat")) { } // Get a FileStream object with write-only permissions. using(FileStream writeOnlyStream = File.OpenWrite(@"Test4.dat")) { } // Get a StreamReader object. using(StreamReader sreader = File.OpenText(@"C:\boot.ini")) { } // Get some StreamWriters. using(StreamWriter swriter = File.CreateText(@"C:\Test3.txt")) { } using(StreamWriter swriterAppend = File.AppendText(@"C:\FinalTest.txt")) { } } Additional File-centric Members The File type also supports a few unique members shown in Table 20-6, which can greatly simplify the processes of reading and writing textual data. CHAPTER 20 ■ FILE I/O AND ISOLATED STORAGE 673 8849CH20.qxd 10/17/07 5:58 PM Page 673 www.free-ebooks-download.org Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com Table 20-6. Methods of the File Type Method Meaning in Life ReadAllBytes() Opens the specified file, returns the binary data as an array of bytes, and then closes the file ReadAllLines() Opens a specified file, returns the character data as an array of strings, and then closes the file ReadAllText() Opens a specified file, returns the character data as a System.String, and then closes the file WriteAllBytes() Opens the specified file, writes out the byte array, and then closes the file WriteAllLines() Opens a specified file, writes out an array of strings, and then closes the file WriteAllText() Opens a specified file, writes the character data, and then closes the file Using these new methods of the File type, you are able to read and write batches of data in just a few lines of code. Even better, each of these new members automatically closes down the under- lying file handle. For example, the following console program (named SimpleFileIO) will persist the string data into a new file on the C drive (and read it into memory) with minimal fuss: using System; using System.IO; class Program { static void Main(string[] args) { Console.WriteLine("***** Simple IO with the File Type *****\n"); string[] myTasks = { "Fix bathroom sink", "Call Dave", "Call Mom and Dad", "Play Xbox 360"}; // Write out all data to file on C drive. File.WriteAllLines(@"C:\tasks.txt", myTasks); // Read it all back and print out. foreach (string task in File.ReadAllLines(@"C:\tasks.txt")) { Console.WriteLine("TODO: {0}", task); } Console.ReadLine(); } } Clearly, when you wish to quickly obtain a file handle, the File type will save you some key- strokes. However, one benefit of first creating a FileInfo object is that you are able to investigate the file using the members of the abstract FileSystemInfo base class. ■Source Code The SimpleFileIO project is located under the Chapter 20 subdirectory. CHAPTER 20 ■ FILE I/O AND ISOLATED STORAGE674 8849CH20.qxd 10/17/07 5:58 PM Page 674 www.free-ebooks-download.org Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com The Abstract Stream Class At this point, you have seen numerous ways to obtain FileStream, StreamReader, and StreamWriter objects, but you have yet to read data from, or write data to, a file using these types. To understand how to do so, you’ll need to become familiar with the concept of a stream. In the world of I/O manipulation, a stream represents a chunk of data flowing between a source and a destination. Streams provide a common way to interact with a sequence of bytes, regardless of what kind of device (file, network connection, printer, etc.) is storing or displaying the bytes in question. The abstract System.IO.Stream class defines a number of members that provide support for synchronous and asynchronous interactions with the storage medium (e.g., an underlying file or memory location). Figure 20-6 shows various descendents of the Stream type, seen through the eyes of the Visual Studio 2008 Object Browser. Figure 20-6. Stream-derived types ■Note Be aware that the concept of a stream is not limited to files IO. To be sure, the .NET libraries provide stream access to networks, memory locations, and other stream-centric abstractions. Again, Stream descendents represent data as a raw stream of bytes; therefore, working directly with raw streams can be quite cryptic. Some Stream-derived types support seeking, which refers to the process of obtaining and adjusting the current position in the stream. To begin understanding the functionality provided by the Stream class, take note of the core members described in Table 20-7. CHAPTER 20 ■ FILE I/O AND ISOLATED STORAGE 675 8849CH20.qxd 10/17/07 5:58 PM Page 675 www.free-ebooks-download.org Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com Table 20-7. Abstract Stream Members Member Meaning in Life CanRead, CanWrite Determine whether the current stream supports reading, seeking, and/or CanSeek writing. Close() Closes the current stream and releases any resources (such as sockets and file handles) associated with the current stream. Internally, this method is aliased to the Dispose() method; therefore “closing a stream” is functionally equivalent to “disposing a stream.” Flush() Updates the underlying data source or repository with the current state of the buffer and then clears the buffer. If a stream does not implement a buffer, this method does nothing. Length Returns the length of the stream, in bytes. Position Determines the position in the current stream. Read(), ReadByte() Read a sequence of bytes (or a single byte) from the current stream and advance the current position in the stream by the number of bytes read. Seek() Sets the position in the current stream. SetLength() Sets the length of the current stream. Write(), WriteByte() Write a sequence of bytes (or a single byte) to the current stream and advance the current position in this stream by the number of bytes written. Working with FileStreams The FileStream class provides an implementation for the abstract Stream members in a manner appropriate for file-based streaming. It is a fairly primitive stream; it can read or write only a single byte or an array of bytes. In reality, you will not often need to directly interact with the members of the FileStream type. Rather, you will most likely make use of various stream wrappers, which make it easier to work with textual data or .NET types. Nevertheless, for illustrative purposes, let’s experi- ment with the synchronous read/write capabilities of the FileStream type. Assume you have a new Console Application named FileStreamApp. Your goal is to write a sim- ple text message to a new file named myMessage.dat. However, given that FileStream can operate only on raw bytes, you will be required to encode the System.String type into a corresponding byte array. Luckily, the System.Text namespace defines a type named Encoding, which provides members that encode and decode strings to (or from) an array of bytes (check out the .NET Framework 3.5 SDK documentation for full details of the Encoding type). Once encoded, the byte array is persisted to file using the FileStream.Write() method. To read the bytes back into memory, you must reset the internal position of the stream (via the Position property) and call the ReadByte() method. Finally, you display the raw byte array and the decoded string to the console. Here is the complete Main() method: // Don't forget to import the System.Text and System.IO namespaces. static void Main(string[] args) { Console.WriteLine("***** Fun with FileStreams *****\n"); // Obtain a FileStream object. using(FileStream fStream = File.Open(@"C:\myMessage.dat", FileMode.Create)) { // Encode a string as an array of bytes. CHAPTER 20 ■ FILE I/O AND ISOLATED STORAGE676 8849CH20.qxd 10/17/07 5:58 PM Page 676 www.free-ebooks-download.org Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com string msg = "Hello!"; byte[] msgAsByteArray = Encoding.Default.GetBytes(msg); // Write byte[] to file. fStream.Write(msgAsByteArray, 0, msgAsByteArray.Length); // Reset internal position of stream. fStream.Position = 0; // Read the types from file and display to console. Console.Write("Your message as an array of bytes: "); byte[] bytesFromFile = new byte[msgAsByteArray.Length]; for (int i = 0; i < msgAsByteArray.Length; i++) { bytesFromFile[i] = (byte)fStream.ReadByte(); Console.Write(bytesFromFile[i]); } // Display decoded messages. Console.Write("\nDecoded Message: "); Console.WriteLine(Encoding.Default.GetString(bytesFromFile)); } Console.ReadLine(); } While this example does indeed populate the file with data, it punctuates the major downfall of working directly with the FileStream type: it demands to operate on raw bytes. Other Stream- derived types operate in a similar manner. For example, if you wish to write a sequence of bytes to a region of memory, you can allocate a MemoryStream. Likewise, if you wish to push an array of bytes through a network connection, you can make use of the NetworkStream type. As mentioned, the System.IO namespace thankfully provides a number of “reader” and “writer” types that encapsulate the details of working with Stream-derived types. ■Source Code The FileStreamApp project is included under the Chapter 20 subdirectory. Working with StreamWriters and StreamReaders The StreamWriter and StreamReader classes are useful whenever you need to read or write charac- ter-based data (e.g., strings). Both of these types work by default with Unicode characters; however, you can change this by supplying a properly configured System.Text.Encoding object reference. To keep things simple, let’s assume that the default Unicode encoding fits the bill. StreamReader derives from an abstract type named TextReader, as does the related StringReader type (discussed later in this chapter). The TextReader base class provides a very lim- ited set of functionality to each of these descendents, specifically the ability to read and peek into a character stream. The StreamWriter type (as well as StringWriter, also examined later in this chapter) derives from an abstract base class named TextWriter. This class defines members that allow derived types to write textual data to a given character stream. To aid in your understanding of the core writing capabilities of the StreamWriter and StringWriter classes, Table 20-8 describes the core members of the abstract TextWriter base class. CHAPTER 20 ■ FILE I/O AND ISOLATED STORAGE 677 8849CH20.qxd 10/17/07 5:58 PM Page 677 www.free-ebooks-download.org Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com Table 20-8. Core Members of TextWriter Member Meaning in Life Close() This method closes the writer and frees any associated resources. In the process, the buffer is automatically flushed (again, this member is functionally equivalent to calling the Dispose() method). Flush() This method clears all buffers for the current writer and causes any buffered data to be written to the underlying device, but does not close the writer. NewLine This property indicates the newline constant for the derived writer class. The default line terminator for the Windows OS is a carriage return followed by a line feed ( \r\n). Write() This overloaded method writes data to the text stream without a newline constant. WriteLine() This overloaded method writes data to the text stream with a newline constant. ■Note The last two members of the TextWriter class probably look familiar to you. If you recall, the System.Console type has Write() and WriteLine() members that push textual data to the standard output device. In fact, the Console.In property wraps a TextWriter, and the Console.Out property wraps a TextReader. The derived StreamWriter class provides an appropriate implementation for the Write(), Close(), and Flush() methods, and it defines the additional AutoFlush property. This property, when set to true, forces StreamWriter to flush all data every time you perform a write operation. Be aware that you can gain better performance by setting AutoFlush to false, provided you always call Close() when you are done writing with a StreamWriter. Writing to a Text File To see the StreamWriter type in action, create a new Console Application named StreamWriterReaderApp. The following Main() method creates a new file named reminders.txt using the File.CreateText() method. Using the obtained StreamWriter object, you add some textual data to the new file, as shown here: static void Main(string[] args) { Console.WriteLine("***** Fun with StreamWriter / StreamReader *****\n"); // Get a StreamWriter and write string data. using(StreamWriter writer = File.CreateText("reminders.txt")) { writer.WriteLine("Don't forget Mother's Day this year "); writer.WriteLine("Don't forget Father's Day this year "); writer.WriteLine("Don't forget these numbers:"); for(int i = 0; i < 10; i++) writer.Write(i + " "); // Insert a new line. writer.Write(writer.NewLine); } CHAPTER 20 ■ FILE I/O AND ISOLATED STORAGE678 8849CH20.qxd 10/17/07 5:58 PM Page 678 www.free-ebooks-download.org Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com Console.WriteLine("Created file and wrote some thoughts "); Console.ReadLine(); } Once you run this program, you can examine the contents of this new file (see Figure 20-7). You will find this file under the bin\Debug folder of your current application, given that you have not specified an absolute path at the time you called CreateText(). Figure 20-7. The contents of your *.txt file Reading from a Text File Now you need to understand how to programmatically read data from a file using the correspon- ding StreamReader type. As you recall, this class derives from the abstract TextReader, which offers the functionality described in Table 20-9. Table 20-9. TextReader Core Members Member Meaning in Life Peek() Returns the next available character without actually changing the position of the reader. A value of -1 indicates you are at the end of the stream. Read() Reads data from an input stream. ReadBlock() Reads a maximum of count characters from the current stream and writes the data to a buffer, beginning at index. ReadLine() Reads a line of characters from the current stream and returns the data as a string (a null string indicates EOF). ReadToEnd() Reads all characters from the current position to the end of the stream and returns them as a single string. If you now extend the current MyStreamWriterReader class to use a StreamReader, you can read in the textual data from the reminders.txt file as shown here: static void Main(string[] args) { Console.WriteLine("***** Fun with StreamWriter / StreamReader *****\n"); // Now read data from file. Console.WriteLine("Here are your thoughts:\n"); using(StreamReader sr = File.OpenText("reminders.txt")) { string input = null; while ((input = sr.ReadLine()) != null) { CHAPTER 20 ■ FILE I/O AND ISOLATED STORAGE 679 8849CH20.qxd 10/17/07 5:58 PM Page 679 www.free-ebooks-download.org Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com Console.WriteLine (input); } } Console.ReadLine(); } Once you run the program, you will see the character data within reminders.txt displayed to the console. Directly Creating StreamWriter/StreamReader Types One of the slightly confusing aspects of working with the types within System.IO is that you can often achieve an identical result using numerous approaches. For example, you have already seen that you can obtain a StreamWriter via the File or FileInfo type using the CreateText() method. In reality, there is yet another way in which you can work with StreamWriters and StreamReaders: create them directly. For example, the current application could be retrofitted as follows: static void Main(string[] args) { Console.WriteLine("***** Fun with StreamWriter / StreamReader *****\n"); // Get a StreamWriter and write string data. using(StreamWriter writer = new StreamWriter("reminders.txt")) { } // Now read data from file. using(StreamReader sr = new StreamReader("reminders.txt")) { } } Although it can be a bit confusing to see so many seemingly identical approaches to file I/O, keep in mind that the end result is greater flexibility. In any case, now that you have seen how to move character data to and from a given file using the StreamWriter and StreamReader types, you will next examine the role of the StringWriter and StringReader classes. ■Source Code The StreamWriterReaderApp project is included under the Chapter 20 subdirectory. Working with StringWriters and StringReaders Using the StringWriter and StringReader types, you can treat textual information as a stream of in-memory characters. This can prove helpful when you wish to append character-based infor- mation to an underlying buffer. To illustrate, the following Console Application (named StringReaderWriterApp) writes a block of string data to a StringWriter object rather than a file on the local hard drive: static void Main(string[] args) { Console.WriteLine("***** Fun with StringWriter / StringReader *****\n"); CHAPTER 20 ■ FILE I/O AND ISOLATED STORAGE680 8849CH20.qxd 10/17/07 5:58 PM Page 680 www.free-ebooks-download.org Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com // Create a StringWriter and emit character data to memory. using(StringWriter strWriter = new StringWriter()) { strWriter.WriteLine("Don't forget Mother's Day this year "); // Get a copy of the contents (stored in a string) and pump // to console. Console.WriteLine("Contents of StringWriter:\n{0}", strWriter); } Console.ReadLine(); } Because StringWriter and StreamWriter both derive from the same base class (TextWriter), the writing logic is more or less identical. However, given that nature of StringWriter, be aware that this class allows you to extract a System.Text.StringBuilder object via the GetStringBuilder() method: using (StringWriter strWriter = new StringWriter()) { strWriter.WriteLine("Don't forget Mother's Day this year "); Console.WriteLine("Contents of StringWriter:\n{0}", strWriter); // Get the internal StringBuilder. StringBuilder sb = strWriter.GetStringBuilder(); sb.Insert(0, "Hey!! "); Console.WriteLine("-> {0}", sb.ToString()); sb.Remove(0, "Hey!! ".Length); Console.WriteLine("-> {0}", sb.ToString()); } When you wish to read from a stream of character data, make use of the corresponding StringReader type, which (as you would expect) functions identically to the related StreamReader class. In fact, the StringReader class does nothing more than override the inherited members to read from a block of character data, rather than a file, as shown here: using (StringWriter strWriter = new StringWriter()) { strWriter.WriteLine("Don't forget Mother's Day this year "); Console.WriteLine("Contents of StringWriter:\n{0}", strWriter); // Read data from the StringWriter. using (StringReader strReader = new StringReader(strWriter.ToString())) { string input = null; while ((input = strReader.ReadLine()) != null) { Console.WriteLine(input); } } } ■Source Code The StringReaderWriterApp is included under the Chapter 20 subdirectory. CHAPTER 20 ■ FILE I/O AND ISOLATED STORAGE 681 8849CH20.qxd 10/17/07 5:58 PM Page 681 www.free-ebooks-download.org Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com [...]... I/O AND ISOLATED STORAGE LastAccess, LastWrite, Security, Size, } The first step you will need to take to work with the FileSystemWatcher type is to set the Path property to specify the name (and location) of the directory that contains the files to be monitored, as well as the Filter property that defines the file extensions of the files to be monitored At this point, you may choose to handle the. .. evidence and print the data to the console window To begin, the Program type provides a Main() method that allows users to enter the full path to the assembly they wish to evaluate If they enter the L option, we will call a helper method that attempts to load the specified assembly into memory If successful, we will pass the Assembly reference to another helper method named DisplayAsmEvidence() Here is the. .. verify, attempt to run any of the IO-centric applications created in this chapter To illustrate, use a command prompt to navigate to the directory containing the DriveInfoApp.exe application created earlier in this chapter Now, attempt to run the program When the runtime error dialog box is displayed, select the Close the Program option, and observe the output in the command window As you can see from... file, and so on) , Zone The name of the zone where the assembly was loaded While the reading of evidence happens automatically, it is possible to programmatically read evidence as well using the reflection APIs and the Evidence type within the System.Security.Policy namespace To deepen your understanding of evidence, create a new Console Application named 68 9 8849CH20.qxd 10/17/07 5:58 PM Page 69 0 Simpo... settings (access to the printer, access to the file system, use of the reflection API, etc.) Using the Microsoft NET Framework Configuration utility, you are able to view the settings for any of the default permission sets simply by selecting the View Permissions link Figure 20- 16 shows the permissions for the Internet permission set, once the View Permissions link has been clicked Each of these icons (File... settings for the My_Computer code group and observe the results Begin by right-clicking the My_Computer_Zone code group for your machine policy using the Microsoft NET Framework Configuration applet to open the related property page Next, click the Permission Set tab, and change the permission set from Full Trust to Internet (see Figure 20-18) 8849CH20.qxd 10/17/07 5:58 PM Page 69 7 Simpo PDF Merge and Split... memory, the CLR will investigate the supplied evidence s Source Code The MyEvidenceViewer project is included under the Chapter 20 subdirectory The Role of Code Groups nl oa d o rg Using evidence, the CLR can then place the assembly into a code group Each code group is mapped to a security zone that has a default out-of -the- box set of security settings the CLR will use to dictate exactly what the assembly... up to further isolate data based on the assembly and/ or application domain identity If you configure isolation and the user + assembly level, the application will be able to use the same store regardless of which application domain is hosting the program In this case, the most specific piece of available evidence (such as a strong name) will be used to create the store name This would allow the end... and Deleted events, all of which work in conjunction with the FileSystemEventHandler delegate This delegate can call any method matching the following pattern: // The FileSystemEventHandler delegate must point // to methods matching the following signature void MyNotificationHandler(object source, FileSystemEventArgs e) nl oa d // The RenamedEventHandler delegate must point // to methods matching the. .. a number of other basic details, such as make use of platform invocation services to call into the API of the operating system (see Figure 20-17) 69 5 8849CH20.qxd 10/17/07 5:58 PM Page 69 6 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com oa d o rg CHAPTER 20 s FILE I/O AND ISOLATED STORAGE w w fr ee -e bo o ks - do w nl Figure 20- 16 Internet permission set w 69 6 Figure 20-17 . shown in Table 20 -6, which can greatly simplify the processes of reading and writing textual data. CHAPTER 20 ■ FILE I/O AND ISOLATED STORAGE 6 73 8849CH20.qxd 10/17/07 5: 58 PM Page 6 73 www.free-ebooks-download.org Simpo. reset the internal position of the stream (via the Position property) and call the ReadByte() method. Finally, you display the raw byte array and the decoded string to the console. Here is the. evidence and print the data to the console window. To begin, the Program type provides a Main() method that allows users to enter the full path to the assembly they wish to evaluate. If they enter the