Тема 13. Потоки данных
Класс Stream
Класс Stream
предоставляет универсальное представление последовательности байтов ( поток байтов ).
Потоки включают три основные операции:
- Чтение из потока — это перенос информации из потока в структуру данных, такую как массив байтов;
- Запись в поток — это передача данных из структуры данных в поток;
- Поиск. Потоки поддерживают поиск. Чтение — это перенос данных из потока в такую структуру данных, как массив байтов. Возможность поиска зависит от вида резервного хранилища потока. Например, в сетевых потоках отсутствует унифицированное представление текущего положения, поэтому обычно они не поддерживают поиск.
Класс Stream
является абстрактным базовым классом всех потоков. Поток — это абстракция последовательности байтов, например файл, устройство ввода-вывода, канал взаимодействия процессов или сокет TCP/IP. Класс Stream
и его производные классы обеспечивают универсальное представление этих различных типов ввода и вывода и программист изолировано от конкретных сведений операционной системы и основных устройств.
В зависимости от лежащих в основе источника или хранилища данных потоки могут поддерживать только некоторые из этих возможностей. Можно запросить поток для ее возможности с помощью CanRead
, CanWrite
и свойства CanSeek
класса Stream
.
Методы Read
и Write
позволяют выполнять чтение и запись данных в различных форматах. Если поток поддерживает поиск, для отправки запросов и изменения текущего положения и длины потока рекомендуется использовать методы Seek
, SetLength
, а также свойства Position
, Length
.
Класс FileStream
Класс FileStream
используется для чтения и записи файлов. Мы можем использовать этот класс для чтения и записи байтов, символов, строк и других типов данных. Класс FileStream
поддерживает синхронное и асинхронное открытие файлов, синхронные операции чтения и записи (методы Read
и Write
), а также асинхронные операции чтения и записи (методы BeginRead
и BeginWrite
). Асинхронные операции завершаются вызовом методов EndRead
и EndWrite
соответственно. Режим по умолчанию — синхронный; для проверки режима мы используем свойство IsAsync
. Для асинхронных операций необходим объект WaitHandle
. Метод Seek
используется для произвольного доступа к файлам. Свойство Position
позволяет нам узнать или установить текущую позицию в потоке. Методы Lock
и Unlock
служат для предотвращения доступа ко всему файлу или к его части, а также для отмены ранее установленного запрета доступа. Свойство Length
возвращает длину потока в байтах, а метод SetLength
служит для задания длины потока. Методы ReadByte
и WriteByte
используются для чтения и записи одного байта. Для других примитивных типов нам необходимы классы BinaryReader
и BinaryWriter
соответственно.
От класса FileStream
наследует класс IsolatedStorageFileSystem
(пространство имен System.IO.IsolatedStorage), служащий для чтения, записи и создания файлов в изолированном хранилище. Изолированное хранилище предоставляет в наше распоряжение виртуальную файловую систему, позволяющую читать и записывать данные, недоступные извне. Изолированное хранилище обеспечивает изоляцию данных на уровне пользователя, сборки или домена приложения.
Чтение из файла
Для чтения данных из потока можно использовать класс StreamReader
. В нем реализовано множество методов для удобного считывания данных. Ниже приведена программа, которая выводит содержимое файла на экран:
static void Main(string[] args)
{
//создаем файловый поток
FileStream file1 =
new FileStream("d:\\test.txt", FileMode.Open);
// создаем «потоковый читатель» и
// связываем его с файловым потоком
StreamReader reader =
new StreamReader(file1);
//считываем все данные с потока и выводим на экран
Console.WriteLine(reader.ReadToEnd());
//закрываем поток
reader.Close();
Console.ReadLine();
}
Метод ReadToEnd()
считывает все данные из файла. ReadLine()
– считывает одну строку (указатель потока при этом переходит на новую строку, и при следующем вызове метода будет считана следующая строка).
Запись в файл
Для записи данных в поток используется класс StreamWriter. Пример записи в файл:
static void Main(string[] args)
{
// создаем файловый поток
FileStream file1 =
new FileStream("d:\\test.txt", FileMode.Create);
// создаем «потоковый писатель» и
// связываем его с файловым потоком
StreamWriter writer =
new StreamWriter(file1);
//записываем в файл
writer.Write("текст");
// закрываем поток.
// если поток не закрыт, возможны ошибки в файле
writer.Close();
}
Метод WriteLine()
записывает в файл построчно (то же самое, что и простая запись с помощью Write()
, только в конце добавляется новая строка).
Нужно всегда помнить, что после работы с потоком, его нужно закрыть (освободить ресурсы), использовав метод Close()
.
Класс MemoryStream
Класс MemoryStream
может использоваться для создания потока, содержимое которого хранится не на диске и не в сети, а в памяти. Этот класс задействует байтовый массив, который может иметь либо фиксированную, либо произвольную длину. В последнем случае мы можем изменять размер массива, читать из него и записывать в него. Что касается потока с фиксированной длиной, то в него мы можем только записывать.
Для того чтобы выяснить число байтов, выделенных под поток в памяти, мы пользуемся свойством Capacity
, возвращающим данные типа Integer
. Свойство Length
возвращает реальное число байтов в потоке (значение типа Long
), а метод GetBuffer()
возвращает массив байтов, в котором располагается поток. Для сохранения всего содержимого потока в байтовом массиве используется метод ToArray()
. Метод WriteTo(Stream)
служит для копирования всего потока в другой поток.
Класс NetworkStream
Этот класс служит для посылки данных по сети. Класс NetworkStream
реализует поток, не поддерживающий операцию позиционирования. Поэтому мы не можем использовать свойство Position
и метод Seek при работе с потоком этого типа.
Текстовые потоки
Базовые потоки обеспечивают ввод/вывод байтов, т.е. двоичной информации. Однако часто требуется обеспечить ввод/вывод текстовой информации. Для реализации ввода/вывода текста необходимо перекодировать потоки бийтов в символы и наоборот. Подобная функциональность достигается применением следующих классов-настроек TextReader, TextWriter, StreamReader, StreamWriter, StringReader, StringWriter.
Дополнительная литература
http://metanit.com/sharp/tutorial/5.4.php
http://metanit.com/sharp/tutorial/5.5.php
http://metanit.com/sharp/tutorial/5.6.php
http://www.mista.ru/net/stream.htm