Составление потоков
Резервное хранилище — это устройство хранения информации, например диск или память. В каждом из резервных хранилищ используется собственный поток как реализация класса Stream. Каждый тип потока считывает и записывает байты в собственное резервное хранилище. Потоки, которые связаны с резервными хранилищами, называются базовыми. В конструкторах базовых потоков есть параметры, необходимые для присоединения потока к резервному хранилищу. Например, FileStream имеет конструктор, задающий путь, который определяет порядок совместного использования файла процессами и т. д.
Структура классов System.IO предоставляет упрощенное составление потоков. Базовые потоки могут быть присоединены к одному или нескольким сквозным потокам, которые обеспечивают требуемую функциональность. Модуль чтения или записи может быть присоединен к концу цепочки, что обеспечит легкое считывание или запись предпочитаемых типов.
В следующем примере кода создается поток FileStream для существующего файла MyFile.txt с целью буферизации файла MyFile.txt. (Обратите внимание, что экземпляры класса FileStreams буферизуются по умолчанию.) Затем создается StreamReader для чтения знаков из FileStream, который передается в StreamReader в качестве аргумента его конструктора. Метод ReadLine считывает до тех пор, пока Peek не находит более символов.
using System;
using System.IO;
public class CompBuf
{
private const string FILE_NAME = "MyFile.txt";
public static void Main(String[] args)
{
if (!File.Exists(FILE_NAME))
{
Console.WriteLine("{0} does not exist!", FILE_NAME);
return;
}
FileStream fsIn = new FileStream(FILE_NAME, FileMode.Open,
FileAccess.Read, FileShare.Read);
// Create an instance of StreamReader that can read
// characters from the FileStream.
StreamReader sr = new StreamReader(fsIn);
// While not at the end of the file, read lines from the file.
while (sr.Peek()>-1)
{
String input = sr.ReadLine();
Console.WriteLine (input);
}
sr.Close();
}
}
Асинхронный файловый ввод-вывод
Синхронный ввод и вывод означает, что метод блокируется до тех пор, пока операция ввода или вывода не будет завершена. Затем метод возвращает данные. С помощью асинхронного ввода и вывода пользователь может вызвать метод BeginRead. Основной поток продолжать выполнять другие операции и получает возможность обработки данных позже. Также множественные запросы ввода и вывода могут обрабатываться одновременно.
Чтобы определить доступность данных, можно вызвать метод EndRead или EndWrite, передавая IAsyncResult в соответствующий запрос ввода и вывода. Можно также указать метод обратного вызова, который будет вызывать метод EndRead или EndWrite, чтобы выяснить, какое количество байтов было считано или записано. Асинхронные ввод и вывод являются более эффективными в том случае, когда одновременно обрабатывается большое количество запросов на ввод и вывод, но, как правило, они требуют значительных изменений в приложении для обеспечения его корректной работы.
Класс Stream поддерживает объединение синхронных и асинхронных операций чтения и записи в один поток независимо от того, допустимо ли это в операционной системе. Stream предоставляет реализацию по умолчанию асинхронных операций чтения и записи на основе синхронных реализаций, а также реализацию по умолчанию синхронных операций чтения и записи на основе асинхронных реализаций.
При реализации класса, производного от Stream, необходимо обеспечить реализацию либо для синхронных, либо для асинхронных методов Read и Write. Хотя переопределение методов Read и Write является допустимым, и по умолчанию реализации асинхронных методов (BeginRead, EndRead, BeginWrite и EndWrite) будут работать с вашей реализацией синхронных методов, это не обеспечивает наиболее высокую производительность. Аналогично, синхронные методы Read и Write также будут работать корректно, если будет предоставлена реализация асинхронных методов. Однако обычно производительность выше, если специально реализовать синхронные методы. По умолчанию реализации ReadByte и WriteByte вызывают синхронные методы Read и Write с одноэлементным массивом байтов. В случае наследования классов от Stream при наличии внутреннего буфера байтов, чтобы получить доступ к внутреннему буферу и тем самым существенно увеличить производительность, рекомендуется переопределять эти методы.
Поток, связанный с резервным хранилищем, переопределяет синхронные или асинхронные методы Read и Write для получения функциональных возможностей других методов по умолчанию. Если поток не поддерживает асинхронные или синхронные операции, то средству реализации необходимо только обеспечить возможность создания исключений соответствующим методом.