Tải bản đầy đủ - 0 (trang)
5-9. Read a File Asynchronously

5-9. Read a File Asynchronously

Tải bản đầy đủ - 0trang

CHAPTER 5 ■ FILES, DIRECTORIES, AND I/O



How It Works

The FileStream includes basic support for asynchronous use through the BeginRead and EndRead

methods. Using these methods, you can read a block of data on one of the threads provided by the .NET

Framework thread pool, without needing to directly use the threading classes in the System.Threading

namespace.

When reading a file asynchronously, you choose the amount of data that you want to read at a time.

Depending on the situation, you might want to read a very small amount of data at a time (for example,

if you are copying it block by block to another file) or a relatively large amount of data (for example, if

you need a certain amount of information before your processing logic can start). You specify the block

size when calling BeginRead, and you pass a buffer where the data will be placed. Because the BeginRead

and EndRead methods need to be able to access many of the same pieces of information, such as the

FileStream, the buffer, the block size, and so on, it’s usually easiest to encapsulate your asynchronous

file reading code in a single class.



The Code

The following example demonstrates reading a file asynchronously. The AsyncProcessor class provides a

public StartProcess method, which starts an asynchronous read. Every time the read operation finishes,

the OnCompletedRead callback is triggered and the block of data is processed. If there is more data in the

file, a new asynchronous read operation is started. AsyncProcessor reads 2 kilobytes (2048 bytes) at a

time.

using System;

using System.IO;

using System.Threading;

namespace Apress.VisualCSharpRecipes.Chapter05

{

public class AsyncProcessor

{

private Stream inputStream;

// The amount that will be read in one block (2KB).

private int bufferSize = 2048;

public int BufferSize

{

get { return bufferSize; }

set { bufferSize = value; }

}

// The buffer that will hold the retrieved data.

private byte[] buffer;

public AsyncProcessor(string fileName)

{

buffer = new byte[bufferSize];



227



www.it-ebooks.info



CHAPTER 5 ■ FILES, DIRECTORIES, AND I/O



// Open the file, specifying true for asynchronous support.

inputStream = new FileStream(fileName, FileMode.Open,

FileAccess.Read, FileShare.Read, bufferSize, true);

}

public void StartProcess()

{

// Start the asynchronous read, which will fill the buffer.

inputStream.BeginRead(buffer, 0, buffer.Length,

OnCompletedRead, null);

}

private void OnCompletedRead(IAsyncResult asyncResult)

{

// One block has been read asynchronously.

// Retrieve the data.

int bytesRead = inputStream.EndRead(asyncResult);

// If no bytes are read, the stream is at the end of the file.

if (bytesRead > 0)

{

// Pause to simulate processing this block of data.

Console.WriteLine("\t[ASYNC READER]: Read one block.");

Thread.Sleep(TimeSpan.FromMilliseconds(20));

// Begin to read the next block asynchronously.

inputStream.BeginRead(

buffer, 0, buffer.Length, OnCompletedRead,

null);

}

else

{

// End the operation.

Console.WriteLine("\t[ASYNC READER]: Complete.");

inputStream.Close();

}

}

}

}



Usage

The following example shows a console application that uses AsyncProcessor to read a 2MB file:

using System;

using System.IO;

using System.Threading;



228



www.it-ebooks.info



CHAPTER 5 ■ FILES, DIRECTORIES, AND I/O



namespace Apress.VisualCSharpRecipes.Chapter05

{

static class Recipe05_09

{

static void Main(string[] args)

{

// Create a test file.

using (FileStream fs = new FileStream("test.txt", FileMode.Create))

{

fs.SetLength(100000);

}

// Start the asynchronous file processor on another thread.

AsyncProcessor asyncIO = new AsyncProcessor("test.txt");

asyncIO.StartProcess();

// At the same time, do some other work.

// In this example, we simply loop for 10 seconds.

DateTime startTime = DateTime.Now;

while (DateTime.Now.Subtract(startTime).TotalSeconds < 2)

{

Console.WriteLine("[MAIN THREAD]: Doing some work.");

// Pause to simulate a time-consuming operation.

Thread.Sleep(TimeSpan.FromMilliseconds(100));

}

Console.WriteLine("[MAIN THREAD]: Complete.");

Console.ReadLine();

// Remove the test file.

File.Delete("test.txt");

}

}

}

The following is an example of the output you will see when you run this test:

[MAIN THREAD]: Doing some work.

[ASYNC READER]: Read one block.

[ASYNC READER]: Read one block.

[MAIN THREAD]: Doing some work.

[ASYNC READER]: Read one block.

[ASYNC READER]: Read one block.



229



www.it-ebooks.info



CHAPTER 5 ■ FILES, DIRECTORIES, AND I/O



[ASYNC READER]: Read one block.

[ASYNC READER]: Read one block.

[MAIN THREAD]: Doing some work.

[ASYNC READER]: Read one block.

[ASYNC READER]: Read one block.

[ASYNC READER]: Read one block.

. . .



5-10. Find Files That Match a Wildcard Expression

Problem

You need to process multiple files based on a filter expression (such as *.dll or mysheet20??.xls).



Solution

Use the overloaded versions of the System.IO.DirectoryInfo.GetFiles or System.IO.DirectoryInfo.

EnumerateFiles methods that accept a filter expression and return an array of FileInfo objects. For

searching recursively across all subdirectories, use the overloaded version that accepts the SearchOption

enumeration.



How It Works

The DirectoryInfo and Directory objects both provide a way to search the directories for files that

match a specific filter expression. These search expressions can use the standard ? and * wildcards. You

can use a similar technique to retrieve directories that match a specified search pattern by using the

overloaded DirectoryInfo.GetDirectories or DirectoryInfo.EnumerateDirectories methods. You can

also use the overload of GetFiles for searching recursively using the SearchOption.AllDirectories

enumeration constant.



The Code

The following example retrieves the names of all the files in a specified directory that match a specified

filter string. The directory and filter expression are submitted as command-line arguments. The code

then iterates through the retrieved FileInfo collection of matching files and displays the name and size

of each one:



230



www.it-ebooks.info



CHAPTER 5 ■ FILES, DIRECTORIES, AND I/O



using System;

using System.IO;

namespace Apress.VisualCSharpRecipes.Chapter05

{

static class Recipe05_10

{

static void Main(string[] args)

{

if (args.Length != 2)

{

Console.WriteLine(

"USAGE: Recipe05_10 [directory] [filterExpression]");

return;

}

DirectoryInfo dir = new DirectoryInfo(args[0]);

FileInfo[] files = dir.GetFiles(args[1]);

// Display the name of all the files.

foreach (FileInfo file in files)

{

Console.Write("Name: " + file.Name + " ");

Console.WriteLine("Size: " + file.Length.ToString());

}

// Wait to continue.

Console.WriteLine(Environment.NewLine);

Console.WriteLine("Main method complete. Press Enter.");

Console.ReadLine();

}

}

}



5-11. Test Two Files for Equality

Problem

You need to quickly compare the content of two files and determine if it matches exactly.



Solution

Calculate the hash code of each file using the System.Security.Cryptography.HashAlgorithm class, and

then compare the hash codes.



231



www.it-ebooks.info



Tài liệu bạn tìm kiếm đã sẵn sàng tải về

5-9. Read a File Asynchronously

Tải bản đầy đủ ngay(0 tr)

×