Когда для записи файла следует использовать объект filestream вместо объекта streamwriter

Обновлено: 05.07.2024

На самом низком уровне иерархии потоков ввода-вывода находятся потоки, оперирующие байтами. Это объясняется тем, что многие устройства при выполнении операций ввода-вывода ориентированы на байты. Однако для человека привычнее оперировать символами, поэтому разработаны символьные потоки, которые фактически представляют собой оболочки, выполняющие преобразование байтовых потоков в символьные и наоборот. Кроме этого, реализованы потоки для работы с int -, double -, short - значениями, которые также представляют оболочку для байтовых потоков, но работают не с самими значениями, а с их внутренним представлением в виде двоичных кодов.

  1. FileStream - байтовый поток, разработанный для файлового ввода-вывода
  2. BufferedStream - заключает в оболочку байтовый поток и добавляет буферизацию, которая во многих случаях увеличивает производительность программы;
  3. MemoryStream - байтовый поток, который использует память для хранения данных.

Программист может вывести собственные потоковые классы. Однако для подавляющего большинства приложений достаточно встроенных потоков.

Подробно мы рассмотрим класс FileStream , классы StreamWriter и StreamReader , представляющие собой оболочки для класса FileStream и позволяющие преобразовывать байтовые потоки в символьные, а также классы BinaryWriter и BinaryReader , представляющие собой оболочки для класса FileStream и позволяющие преобразовывать байтовые потоки в двоичные для работы с int -, double -, short - и т.д. значениями.

Байтовый поток

Чтобы создать байтовый поток, связанный с файлом, создается объект класса FileStream . При этом в классе определено несколько конструкторов. Чаще всего используется конструктор, который открывает поток для чтения и/или записи:

  1. параметр filename определяет имя файла, с которым будет связан поток ввода-вывода данных; при этом filename определяет либо полный путь к файлу, либо имя файла, который находится в папке bin/debug вашего проекта.
  2. параметр mode определяет режим открытия файла, который может принимать одно из возможных значений, определенных перечислением FileMode :
    • FileMode.Append - предназначен для добавления данных в конец файла;
    • FileMode.Create - предназначен для создания нового файла, при этом если существует файл с таким же именем, то он будет предварительно удален;
    • FileMode. CreateNew - предназначен для создания нового файла, при этом файл с таким же именем не должен существовать;
    • FileMоde.Open - предназначен для открытия существующего файла;
    • FileMode.ОpenOrCreate - если файл существует, то открывает его, в противном случае создает новый
    • FileMode.Truncate - открывает существующий файл, но усекает его длину до нуля

Если попытка открыть файл оказалась неуспешной, то генерируется одно из исключений: FileNotFoundException - файл невозможно открыть по причине его отсутствия, IOException - файл невозможно открыть из-за ошибки ввода-вывода, ArgumentNullException - имя файла представляет собой null -значение, ArgumentException - некорректен параметр mode, SecurityException - пользователь не обладает правами доступа, DirectoryNotFoundException - некорректно задан каталог.

Другая версия конструктора позволяет ограничить доступ только чтением или только записью:

  1. параметры filename и mode имеют то же назначение, что и в предыдущей версии конструктора;
  2. параметр how, определяет способ доступа к файлу и может принимать одно из значений, определенных перечислением FileAccess :
  1. FileAccess.Read - только чтение;
  2. FileAccess.Write - только запись;
  3. FileAccess.ReadWrite - и чтение, и запись.

После установления связи байтового потока с физическим файлом внутренний указатель потока устанавливается на начальный байт файла.

Для чтения очередного байта из потока, связанного с физическим файлом, используется метод ReadByte() . После прочтения очередного байта внутренний указатель перемещается на следующий байт файла. Если достигнут конец файла, то метод ReadByte() возвращает значение -1 .

Для побайтовой записи данных в поток используется метод WriteByte() .

По завершении работы с файлом его необходимо закрыть. Для этого достаточно вызвать метод Close () . При закрытии файла освобождаются системные ресурсы, ранее выделенные для этого файла, что дает возможность использовать их для работы с другими файлами.

Рассмотрим пример использования класса FileStream , для копирования одного файла в другой. Но вначале создадим текстовый файл text.txt в папке bin/debug текущего проекта. И внесем в него произвольную информацию, например:

Задание. Подумайте, почему для переменной i указан тип int . Можно было бы указать тип byte ?

Символьный поток

Чтобы создать символьный поток нужно поместить объект класса Stream (например, FileStream ) "внутрь" объекта класса StreamWriter или объекта класса StreamReader . В этом случае байтовый поток будет автоматически преобразовываться в символьный.

Класс StreamWriter предназначен для организации выходного символьного потока. В нем определено несколько конструкторов. Один из них записывается следующим образом:

где параметр stream определяет имя уже открытого байтового потока.

Например, создать экземпляр класса StreamReader можно следующим образом:

Этот конструктор генерирует исключение типа ArgumentException , если поток stream не открыт для вывода, и исключение типа ArgumentNullException , если он (поток) имеет null-значение.

Другой вид конструктора позволяет открыть поток сразу через обращения к файлу:

где параметр name определяет имя открываемого файла.

Например, обратиться к данному конструктору можно следующим образом:

И еще один вариант конструктора StreamWriter :

где параметр name определяет имя открываемого файла;

параметр appendFlag может принимать значение true - если нужно добавлять данные в конец файла, или false - если файл необходимо перезаписать.

Теперь для записи данных в поток fileOut можно обратиться к методу WriteLine . Это можно сделать следующим образом:

В данном случае в конец файла t.txt будет дописано слово test .

Класс StreamReader предназначен для организации входного символьного потока. Один из его конструкторов выглядит следующим образом:

где параметр stream определяет имя уже открытого байтового потока.

Этот конструктор генерирует исключение типа ArgumentException , если поток stream не открыт для ввода.

Например, создать экземпляр класса StreamWriter можно следующим образом:

Как и в случае с классом StreamWriter у класса StreamReader есть и другой вид конструктора, который позволяет открыть файл напрямую:

где параметр name определяет имя открываемого файла.

Обратиться к данному конструктору можно следующим образом:

Параметр Encoding.GetEncoding(1251) говорит о том, что будет выполняться преобразование из кода Windows-1251 (одна из модификаций кода ASCII, содержащая русские символы) в Unicode. Encoding.GetEncoding(1251) реализован в пространстве имен System.Text .

Теперь для чтения данных из потока fileIn можно воспользоваться методом ReadLine . При этом если будет достигнут конец файла, то метод ReadLine вернет значение null.

Рассмотрим пример, в котором данные из одного файла копируются в другой, но уже с использованием классов StreamWriter и StreamReader .

Задание. Выясните, для чего предназначен метод ReadToEnd() и когда имеется смысл его применять.

Таким образом, данный способ копирования одного файла в другой, даст нам тот же результат, что и при использовании байтовых потоков. Однако, его работа будет менее эффективной, т.к. будет тратиться дополнительное время на преобразование байтов в символы. Но у символьных потоков есть свои преимущества. Например, мы можем использовать регулярные выражения для поиска заданных фрагментов текста в файле.

чем отличается FileStream от StreamWriter в dotnet?

какой контекст вы должны использовать? В чем их преимущество и недостаток?

можно ли объединить эти два в один?

чем отличается FileStream от StreamWriter в dotnet?

A FileStream Это Stream . Как и все потоки, он имеет дело только с byte[] данные.

A StreamWriter : TextWriter , является поток-декоратор. TextWriter кодирует текстовые данные, такие как string или char в byte[] а затем записывает его в связанный Stream .

какой контекст вы должны использовать? В чем их преимущество и недостаток?

вы используете голый FileStream, когда у вас есть byte[] данные. Добавить StreamWriter если вы хотите написать текст. Используйте форматер или сериализатор для записи более сложных данных.

можно ли объединить эти два в один?

да. Вам всегда нужен поток для создания StreamWriter. Вспомогательный метод System.IO.File.CreateText("path") создаст их в комбинации, а затем вам нужно будет только Dispose () внешний писатель.

FileStream пишет байты, StreamWriter пишет текст. Вот и все.

FileStream явно предназначен для рабочих файлов.

StreamWriter может использоваться для потока в любой тип поток - сетевые сокеты, файлы и т. д.

предоставляет Stream в файл, поддерживающий синхронные и асинхронные операции чтения и записи.

реализует textwriter для записи символов в поток в определенной кодировке.

самая очевидная разница в том, что FileStream позволяет осуществлять операции чтения/записи, в то время как StreamWriter это пишут только.

на StreamWriter страница продолжает добавлять:

StreamWriter предназначен для вывода символов в определенной кодировке, тогда как классы, производные от Stream, предназначены для ввода и вывода байтов.

Итак, вторая разница в том, что FileStream для байтов, в то время как StreamWriter для текста.

Это два разных уровня, используемых для вывода информации в известные источники данных.

FileStream - это тип потока, который концептуально является механизмом, указывающим на некоторое местоположение и может обрабатывать входящие и/или исходящие данные В и из этого местоположения. Существуют потоки для чтения / записи в файлы, сетевые подключения, память, каналы, консоль, прослушиватели отладки и трассировки и несколько других типов источников данных. В частности, FileStream существует для выполнения чтения и запись в файловую систему. Большинство потоков довольно низкоуровневые в своем использовании и имеют дело с данными в виде байтов.

StreamWriter-это оболочка для потока, которая упрощает использование этого потока для вывода простого текста. Он предоставляет методы, которые принимают строки вместо байтов, и выполняет необходимые преобразования в и из байтовых массивов. Есть и другие авторы; другой основной, который вы бы использовали, - XmlTextWriter, который облегчает запись данных в формате XML. Есть также читатель аналоги авторы, которые аналогичным образом обернуть поток и облегчить получение данных обратно.

одно ключевое отличие (в дополнение к приведенным выше комментариям) может заключаться в том, что FileStream поддерживает случайное чтение и запись на диск в любой указанный FileStream.Позиция. Для больших модификаций файлов это может быть бесценно.

Некоторые сведения относятся к предварительной версии продукта, в которую до выпуска могут быть внесены существенные изменения. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.

Предоставляет Stream в файле, поддерживая синхронные и асинхронные операции чтения и записи.

Примеры

В следующем примере показаны некоторые FileStream конструкторы.

В следующем примере показано, как выполнить запись в файл асинхронно. Этот код выполняется в приложении WPF с элементом управления TextBlock с именем UserInput и кнопкой, привязанной к обработчику событий щелчка, который называется Button_Click. Путь к файлу необходимо заменить на файл, существующий на компьютере.

Комментарии

Используйте FileStream класс для чтения, записи, открытия и закрытия файлов в файловой системе, а также для управления другими дескрипторами операционной системы, связанными с файлами, включая каналы, стандартные входные и стандартные выходные данные. Read Write Методы,, и можно использовать CopyTo Flush для выполнения синхронных операций или ReadAsync WriteAsync методов,, CopyToAsync и FlushAsync для выполнения асинхронных операций. Используйте асинхронные методы для выполнения ресурсоемких файловых операций без блокировки основного потока. Это соображение, связанное с производительностью, особенно важно в приложениях Магазина Windows 8.x и классических приложениях, в которых длительная потоковая операция может блокировать поток пользовательского интерфейса и создавать впечатление, что приложение не работает. FileStream буферизация входных и выходных данных для повышения производительности.

IsAsyncСвойство определяет, был ли этот файл открыт асинхронно. Это значение указывается при создании экземпляра FileStream класса с помощью конструктора, который имеет isAsync useAsync параметр, или options . Если свойство имеет значение true , поток использует перекрывающиеся операции ввода-вывода для асинхронного выполнения операций с файлами. Однако IsAsync свойство не обязательно должно true вызывать ReadAsync WriteAsync метод, или CopyToAsync . Если IsAsync свойство имеет значение false и вызываются асинхронные операции чтения и записи, то поток пользовательского интерфейса по-прежнему не блокируется, но фактическая операция ввода-вывода выполняется синхронно.

SeekМетод поддерживает произвольный доступ к файлам. Seek позволяет переместить расположение для чтения и записи в любое расположение в файле. Это делается с помощью параметров точки ссылки смещения в байтах. Смещение в байтах задается относительно точки ссылки поиска, которая может быть началом, текущей позицией или концом базового файла, как представлено тремя элементами SeekOrigin перечисления.

Файлы на диске всегда поддерживают произвольный доступ. Во время создания CanSeek значение свойства устанавливается в true или в false зависимости от базового типа файла. Если базовым типом файла является FILE_TYPE_DISK, как определено в винбасе. h, CanSeek свойство имеет значение true . В противном случае CanSeek значение свойства равно false .

Если процесс завершается с заблокированной частью файла или закрывает файл с необработанными блокировками, поведение не определено.

Сведения об операциях с каталогами и других файловых операциях см. в разделе File Directory классы, и Path . FileКласс — это служебный класс, который имеет статические методы в основном для создания FileStream объектов на основе путей к файлам. MemoryStreamКласс создает поток из массива байтов и аналогичен FileStream классу.

Список общих операций с файлами и каталогами см. в разделе Общие задачи ввода-вывода.

Обнаружение изменений в положении потока

Если у FileStream объекта нет монопольного удержания на его обработчике, другой поток может одновременно получить доступ к этому обработчику файлов и изменить расположение указателя файла операционной системы, связанного с этим обработчиком файлов. В этом случае кэшированное расположение в FileStream объекте и кэшированные данные в буфере могут быть скомпрометированы. FileStreamОбъект, как правило, выполняет проверки методов, обращающихся к кэшированному буферу, чтобы убедиться, что расположение маркера операционной системы совпадает с кэшированной позицией, используемой FileStream объектом.

Если в вызове метода обнаружено непредвиденное изменение в положении Handle Write , содержимое буфера удаляется и IOException создается исключение.

FileStreamУ объекта не будет монопольного удержания на его обработку, когда доступ к SafeFileHandle свойству предоставляется для доступа к обработчику, или FileStream объект получает SafeFileHandle свойство в своем конструкторе.

Конструкторы

Инициализирует новый экземпляр класса FileStream для заданного дескриптора файла, используя указанные разрешения на чтение и запись.

Инициализирует новый экземпляр класса FileStream для заданного дескриптора файла, используя указанные разрешения на чтение и запись и владельца экземпляра FileStream .

Инициализирует новый экземпляр класса FileStream для заданного дескриптора файла, используя указанные разрешения на чтение и запись, владельца экземпляра FileStream и размер буфера.

Инициализирует новый экземпляр класса FileStream для заданного дескриптора файла, используя указанные разрешения на чтение и запись, владельца экземпляра FileStream , размер буфера и синхронное или асинхронное состояние.

Инициализирует новый экземпляр класса FileStream для заданного дескриптора файла, используя указанные разрешения на чтение и запись.

Инициализирует новый экземпляр класса FileStream для заданного дескриптора файла, используя указанные разрешения на чтение и запись и размер буфера.

Инициализирует новый экземпляр класса FileStream для заданного дескриптора файла, используя указанные разрешения на чтение и запись, размер буфера и синхронное или асинхронное состояние.

Инициализирует новый экземпляр класса FileStream указанным путем и режимом создания.

Инициализирует новый экземпляр класса FileStream заданным путем, режимом создания и разрешением на чтение и запись.

Инициализирует новый экземпляр класса FileStream заданным путем, режимом создания, разрешением на чтение и запись и разрешением на совместное использование.

Инициализирует новый экземпляр класса FileStream заданным путем, режимом создания, разрешениями на чтение и запись и на совместное использование, а также размером буфера.

Инициализирует новый экземпляр класса FileStream заданным путем, режимом создания, разрешениями на чтение и запись и совместное использование, размером буфера и синхронным или асинхронным состоянием.

Инициализирует новый экземпляр класса FileStream заданным путем, режимом создания, разрешениями на чтение, запись и совместное использование, доступом для других FileStreams к этому же файлу, размером буфера и дополнительными параметрами файла.

Инициализирует новый экземпляр класса FileStream заданным путем, режимом создания, разрешениями на чтение, запись и совместное использование, размером буфера и дополнительными параметрами файла.

Инициализирует новый экземпляр класса FileStream заданными путем, режимом создания, правами на доступ и совместное использование, размером буфера, дополнительными параметрами файла, управлением доступом и аудитом безопасности.

Инициализирует новый экземпляр FileStream класса с заданным путем, режимом создания, разрешением на чтение, запись и совместное использование, доступ к другим потокам FILESTREAM может иметь один и тот же файл, размер буфера, дополнительные параметры файла и размер выделения.

Свойства

Получает значение, указывающее, поддерживает ли текущий поток чтение.

Получает значение, указывающее, поддерживает ли текущий поток поиск.

Возвращает значение, которое показывает, может ли для данного потока истечь время ожидания.

Получает значение, указывающее, поддерживает ли текущий поток запись.

Возвращает дескриптор файла операционной системы для файла, инкапсулируемого текущим объектом FileStream .

Получает значение, указывающее, как был открыт FileStream : синхронно или асинхронно.

Получает длину потока в байтах.

Получает абсолютный путь к файлу, открытому в функции FileStream .

Возвращает или задает текущую позицию этого потока.

Возвращает или задает значение в миллисекундах, определяющее период времени, отведенного потоку на выполнение операции чтения.

Возвращает объект SafeFileHandle, представляющий дескриптор файла операционной системы для файла, инкапсулируемого текущим объектом FileStream.

Возвращает или задает значение в миллисекундах, определяющее период времени, отведенного потоку на выполнение операции записи.

Методы

Начинает операцию асинхронного чтения. Вместо него рекомендуется использовать класс ReadAsync(Byte[], Int32, Int32, CancellationToken).

Начинает операцию асинхронного чтения. (Рекомендуется использовать ReadAsync(Byte[], Int32, Int32).)

Начинает операцию асинхронной записи. Вместо него рекомендуется использовать класс WriteAsync(Byte[], Int32, Int32, CancellationToken).

Начинает операцию асинхронной записи. (Рекомендуется использовать WriteAsync(Byte[], Int32, Int32).)

Закрывает текущий поток и отключает все ресурсы (например, сокеты и файловые дескрипторы), связанные с текущим потоком.

Закрывает текущий поток и отключает все ресурсы (например, сокеты и файловые дескрипторы), связанные с текущим потоком. Вместо вызова данного метода, убедитесь в том, что поток надлежащим образом ликвидирован.

Считывает байты из текущего потока и записывает их в другой поток.

Считывает байты из текущего потока и записывает их в другой поток, используя указанный размер буфера.

Асинхронно считывает байты из текущего потока и записывает их в другой поток.

Асинхронно считывает байты из текущего потока и записывает их в другой поток, используя указанный токен отмены.

Асинхронно считывает байты из текущего потока и записывает их в другой поток, используя указанный размер буфера.

Асинхронно считывает байты из текущего файлового потока и записывает их в другой поток, используя указанный размер буфера и токен отмены.

Асинхронно считывает байты из текущего потока и записывает их в другой поток, используя указанный размер буфера и токен отмены.

Создает объект, который содержит всю необходимую информацию для создания прокси-сервера, используемого для взаимодействия с удаленным объектом.

Освобождает все ресурсы, занятые модулем Stream.

Освобождает неуправляемые ресурсы, используемые объектом FileStream, а при необходимости освобождает также управляемые ресурсы.

Асинхронно освобождает неуправляемые ресурсы, используемые классом FileStream.

Асинхронно освобождает неуправляемые ресурсы, используемые классом Stream.

Ожидает завершения отложенной асинхронной операции чтения. (Рекомендуется использовать ReadAsync(Byte[], Int32, Int32, CancellationToken).)

Ожидает завершения отложенного асинхронного чтения. (Рекомендуется использовать ReadAsync(Byte[], Int32, Int32).)

Завершает асинхронную операцию записи и блокирует до тех пор, пока не будет завершена операция ввода-вывода. (Рекомендуется использовать WriteAsync(Byte[], Int32, Int32, CancellationToken).)

Заканчивает операцию асинхронной записи. (Рекомендуется использовать WriteAsync(Byte[], Int32, Int32).)

Определяет, равен ли указанный объект текущему объекту.

Гарантирует, что ресурсы освобождены и выполнены другие операции очистки, когда сборщик мусора восстанавливает FileStream .

Очищает буферы для этого потока и вызывает запись всех буферизованных данных в файл.

Очищает буферы для этого потока и вызывает запись всех буферизованных данных в файл, а также очищает все буферы промежуточных файлов.

Асинхронно очищает все буферы для этого потока и вызывает запись всех буферизованных данных в базовое устройство.

Асинхронно очищает все буферы данного потока, вызывает запись буферизованных данных в базовое устройство и отслеживает запросы отмены.

Асинхронно очищает все буферы данного потока, вызывает запись буферизованных данных в базовое устройство и отслеживает запросы отмены.

Возвращает объект FileSecurity, который инкапсулирует записи списка управления доступом (ACL) для файла, описываемого текущим объектом FileStream.

Служит хэш-функцией по умолчанию.

Извлекает объект обслуживания во время существования, который управляет политикой времени существования данного экземпляра.

Возвращает объект Type для текущего экземпляра.

Получает объект службы времени существования для управления политикой времени существования для этого экземпляра.

Запрещает другим процессам чтение объекта FileStream и запись в этот объект.

Создает неполную копию текущего объекта Object.

Создает неполную копию текущего объекта MarshalByRefObject.

Обеспечивает поддержку для Contract.

Выполняет чтение блока байтов из потока и запись данных в заданный буфер.

Считывает последовательность байтов из текущего файлового потока и перемещает позицию внутри файлового потока на число считанных байтов.

При переопределении в производном классе считывает последовательность байтов из текущего потока и перемещает позицию в потоке на число считанных байтов.

Асинхронно считывает последовательность байтов из текущего потока и перемещает позицию внутри потока на число считанных байтов.

Асинхронно считывает последовательность байтов из текущего файлового потока, записывает их в массив байтов по заданному смещению, перемещает позицию в файловом потоке на число считанных байтов и отслеживает запросы отмены.

Асинхронно считывает последовательность байтов из текущего потока, перемещает позицию в потоке на число считанных байтов и отслеживает запросы отмены.

Асинхронно считывает последовательность байтов из текущего файлового потока, записывает их в область памяти, перемещает позицию в файловом потоке на число считанных байтов и отслеживает запросы отмены.

Асинхронно считывает последовательность байтов из текущего потока, перемещает позицию в потоке на число считанных байтов и отслеживает запросы отмены.

Считывает байт из файла и перемещает положение чтения на один байт.

Устанавливает текущее положение этого потока на заданное значение.

Применяет записи списка управления доступом (ACL), описанные объектом FileSecurity, к файлу, который описывается текущим объектом FileStream.

Устанавливает длину этого потока на заданное значение.

Возвращает строку, представляющую текущий объект.

Разрешает доступ других процессов ко всему ранее заблокированному файлу или его части.

Записывает блок байтов в файловый поток.

Записывает последовательность байтов в текущий файловый поток из диапазона только для чтения и перемещает текущую позицию внутри файлового потока на число записанных байтов.

При переопределении в производном классе записывает последовательность байтов в текущий поток и перемещает текущую позицию в нем вперед на число записанных байтов.

Асинхронно записывает последовательность байтов в текущий поток и перемещает текущую позицию внутри потока на число записанных байтов.

Асинхронно записывает последовательность байтов в текущий поток, перемещает текущую позицию внутри потока на число записанных байтов и отслеживает запросы отмены.

Асинхронно записывает последовательность байтов в текущий поток, перемещает текущую позицию внутри потока на число записанных байтов и отслеживает запросы отмены.

Асинхронно записывает последовательность байтов из области памяти в текущий файловый поток, перемещает текущую позицию внутри файлового потока на число записанных байтов и отслеживает запросы отмены.

Асинхронно записывает последовательность байтов в текущий поток, перемещает текущую позицию внутри потока на число записанных байтов и отслеживает запросы отмены.

Запись байта в текущую позицию в потоке файла.

Явные реализации интерфейса

Освобождает все ресурсы, занятые модулем Stream.

Методы расширения

Возвращает сведения о безопасности для файла.

Изменяет атрибуты безопасности для существующего файла.

Преобразует заданный поток в поток прямого доступа.

Настраивает способ выполнения ожиданий для задач, возвращаемых из асинхронного высвобождаемого объекта.

Для изучения данного вопроса будем использовать проект решения предыдущего параграфа, убрав, как обычно, коды обработчиков событий нажатия кнопок и оставив все контролы и коды обработчика нажатия кнопки 3 и функцию Form1_Load.

абстрактным классом Stream и его наследниками, обеспечивающими возможности манипулирования последовательностями байтов;

прямыми наследниками класса Object - классами BinaryReader и BinaryWriter, предназначенными для чтения и записи примитивных типов данных;

наследниками абстрактного класса TextReader - StreamWriter и StreamReader, использующимися для чтения и записи последовательности символов;

Потоки для работы с последовательностями байтов

В предыдущем параграфе при рассмотрении пространства имен IO было отмечено, что класс Stream - наследник абстрактного класса MarhalByRefObject - также абстрактный класс, обеспечивающий представление последовательности байтов. Классы наследники класса Stream, обеспечивают функции для работы с файлами (класс FileStream), памятью (класс MemoryStream) и дают возможность создать буфер в памяти для буферизованных потоковых операций чтения и записи (BufferedStream). Потоки поддерживают операции чтения, записи, а также операции позиционирования. Из наследников абстрактного класса Stream следует упомянуть о еще двух классах из другого пространства имен - классах NetworkStream (класс для посылки данных по сети) и CryptoStream (класс для криптографических преобразований), которые имеют схожие и отличные свойства и методы от методов потоков пространства имен IO, что пока также выходит за границу задач данного раздела.

Базовый класс Stream

Методы используемые для начала и завершения асинхронных операции чтения и записи:

- Метод BeginRead(byte[] buffer,int offset,int count,AsyncCallback callback,object state);

Начать асинхронную операцию чтения.

Параметры: buffer - буфер данных, offset - смещение байта в потоке, count - максимальное число байтов для чтения, callback - параметр типа AsyncCallback или проще - функция делегат, которая вызывается при завершении операций чтения записи, state - параметр типа AsyncState доступный через свойства AsyncState интерфейса IAsyncResult и возвращающий метод IAsyncResult. Тоесть это объект(класс), который может быть создан и заполнен пользователем некоторой информацией, которая в той или иной степени отражает состояние этапа вызова асинхронной операции, и может быть использована в дальнейшем или при прерывании или в функции обратного вызова, имя объекта доступно в функции callback.

Возвращаемое значение - IAsyncResult - интерфейс при помощи которого программа может получить информацию о состоянии асинхронной операции.

Метод вызывает прерывания IOException при выходе за границы файла (потока) и сбоях на дисках, ArgumentException - при недопустимых параметрах, ObjectDisposedException Methods - при вызовах методов для закрытого потока, NotSupportedException - если поток не поддерживает метод.

Подробный пример по работе с асинхронными методами будет рассмотрен после рассмотрения метода EndRead() (см. ниже).

- Метод EndRead(IAsyncResult asyncResult); завершает асинхронное чтение.

Возвращаемое значение число прочитанных байт.

Метод вызывает прерывания ArgumentNullException asyncResult - при нулевой ссылки параметра, ArgumentException - когдат объект IASYNCRESULT не был создан вызовом BeginRead и InvalidOperationException - при множественном вызове.

Пример работы с асинхронными методами

Для начала создаем отдельный процесс, который будет вызывать асинхронный метод и при длительной операции чтения или записи выполнение которого может быть приостановлено.

В функции AsynchronRead собственно и будет вызов асинхронного метода чтения из файла:

Структурра и функция обратного вызова используемые при вызове асинхронного метода:

Код примера выводит содержимое текстового файла только после окончания операции чтения. То, что это так, легко убедиться закоментировав строку situation.manualresetevent.Set(); в функции EndAsingRead - в этом случае данные не будут выведены вообще.

- Метод BeginWrete(byte[] buffer,int offset,int count,AsyncCallback callback,object state);

Начать асинхронную операцию записи.

Параметры: buffer - буфер данных, offset - смещение байта в потоке, count - максимальное число байтов для чтения, callback - параметр типа AsyncCallback или проще - функция делегат, которая вызывается при завершении операций чтения записи, state - параметр типа AsyncState доступный через свойства AsyncState интерфейса IAsyncResult и возвращающий метод IAsyncResult. Тоесть это объект(класс), который может быть создан и заполнен пользователем некоторой информацией, которая в той или иной степени отражает состояние этапа вызова асинхронной операции, и может быть использована в дальнейшем или при прерывании или в функции обратного вызова, имя объекта доступно в функции callback.

Возвращаемое значение - IAsyncResult - интерфейс при помощи которого программа может получить информацию о состоянии асинхронной операции.

Метод вызывает прерывания IOException при ошибках ввода/вывода, ArgumentException - при недопустимых параметрах когда смещение или индекс находятся в недопустимых пределах, ObjectDisposedException Methods - при вызовах методов для закрытого потока, NotSupportedException - если поток не поддерживает метод, ArgumentOutOfRangeException - смещение или индекс отрицательны, ArgumentNullException при нулевой ссылке на массив.

Как видно параметры и прерывания для BeginWrete полностью аналогичны параметрам и прерываниям метода BeginRead, как аналогичен и алгоритм использования метода в приведенном выше примере, в котором достаточно поменять BeginRead на BeginWrete и заранее заполнить источник situation.bText требуемой информацией, а в функции обратного вызова использовать метод EndWrite вместо EndRead. Всилу этого, пример для данного метода не приводится - каждый может легко использовать (приведенный выше пример).

- Метод EndWrete(IAsyncResult asyncResult); завершает асинхронную запись.

Возвращаемого значения нет.

Метод вызывает прерывания ArgumentNullException asyncResult - при нулевой ссылки параметра, ArgumentException - когдат объект IASYNCRESULT не был создан вызовом BeginRead и InvalidOperationException - при множественном вызове. О использовании метода мы уже говорили при описании метода BeginWrete.

Синхронные методы чтения записи:

- Метод ReadByte() - читает один байт из файла и продвигает указатель на один байт.

Возвращаемое значение - прочитанный байт.

Запишем в файл C:\a.txt числа 0123456789 и выполним следующий код:

Результат в TextBox

Кроме того в примере использован метод Seek устанавливающий текущую позицию в потоке на первый (отсчет от нуля) байт.

- Метод WriteByte(byte value) - записывает байт с текущей позиции в потоке и продвигает указатель на один байт.

Возвращаемого значения нет.

Метод вызывает прерывания ObjectDisposedException Methods - при вызовах методов для закрытого потока, NotSupportedException - если поток не поддерживает метод.

- Метод Read(bute[] buffer,int offset,int count) - читает блок размером count байт из потока с позиции байта offset и пишет данные в буфер buffer или массив байт.

Возвращаемое значение - общее число прочитанных байт или "0" - если достигнут конец потока. Если операция чтения успешна, текущая позиция потока продвигается на count байт.

Метод вызывает прерывания IOException при ошибках ввода/вывода, ArgumentException - при недопустимых параметрах когда смещение или индекс находятся в недопустимых пределах, ObjectDisposedException Methods - при вызовах методов для закрытого потока, NotSupportedException - если поток не поддерживает метод, ArgumentOutOfRangeException - смещение или индекс отрицательны, ArgumentNullException при нулевой ссылке на массив.

Пример использования метода:

- Метод Write(bute[] buffer,int offset,int count) - пишет блок размером count байт в поток с позиции байта offset из буфера байт buffer.

Возвращаемое значение - нет.

Метод вызывает прерывания IOException при ошибках ввода/вывода, ArgumentException - при недопустимых параметрах когда смещение или индекс находятся в недопустимых пределах, ObjectDisposedException Methods - при вызовах методов для закрытого потока, NotSupportedException - если поток не поддерживает метод, ArgumentOutOfRangeException - смещение или индекс отрицательны, ArgumentNullException при нулевой ссылке на массив байт.

Пример использования метода (изменим код примера для метода WriteByte и получим тотже результат):

- Метод Seek(long offset, SeekOrigin origin) - метод измененяет текущую позиции в потоке (использование см. выше и ниже в примерах) и возвращает новую позицию указателя в потоке в форме числа типа long.

Метод может вызвать прерывания IOException - если указатель файла перемещен в недопустимое местоположение или ArgumentException - значение SeekOrigin недопустимо для данного местоположения указателя.

Параметры: offset - cмещение от начала, конца или текущей позиции, origin - значение типа SeekOrigin, определяющее начало, конец, или текущую позицию.

Возможные прерывания как и у методов чтения записи: NotSupportedException - поток не поддерживает позиционирование, IOException - при ошибках ввода вывода, а также ArgumentException - при установке указателя вне размера потока и ObjectDisposedException - метод вызван для закрытого потока.

Метод изменения длины потока

- SetLength(long value) - метод изменяет длину текущего потока и возвращает новую позицию указателя в потоке;

Параметр value - новая длина потока.

Возможные прерывани: NotSupportedException - поток не поддерживает установку размеров, IOException - при ошибках ввода вывода, а также ArgumentOutOfRangeException - при попытке установить параметр длины меньше нуля.

Метод очистки буфера

- МетодFlush() - очищает все буфера для данного потока и заставляет записать в поток все буферизованные данные;

Метод вызывает прерывание IOException при ошибке ввода/вывода и ObjectDisposedException - при применении метода к закрытому потоку.

Метод закрытия потока

- МетодClose() - метод закрывает текущий поток и освобождает все ресурсы, связанные с текущим потоком и файлом.

Метод вызывает прерывание IOException если ошибка произошла при попытке закрыть поток.

Читайте также: