В этой главе речь пойдет о средствах консольного и файлового ввода-вывода. Следует, однако, сразу же предупредить, что система ввода-вывода в C# довольно обширна. Поэтому в этой главе рассматриваются лишь самые важные и наиболее часто используемые ее средства.
Организация системы ввода-вывода в C# на потоках
Ввод-вывод в программах на C# осуществляется посредством потоков.
На самом низком уровне ввод-вывод в C# осуществляется байтами. И делается это потому, что многие устройства ориентированы на операции ввода-вывода отдельными байтами. Но человеку больше свойственно общаться символами. Напомним, что в C# тип char
является 16-разрядным, а тип byte
— 8-разрядным. Так, если в целях ввода-вывода используется набор символов в коде ASCII, то для преобразования типа char
в тип byte
достаточно отбросить старший байт значения типа char
. Но это не годится для набора символов в уникоде (Unicode
), где символы требуется представлять двумя, а то и больше байтами. Следовательно, байтовые потоки не совсем подходят для организации ввода-вывода отдельными символами. С целью разрешить это затруднение в среде .NET Framework определено несколько классов, выполняющих превращение байтового потока в символьный с автоматическим преобразованием типа byte
в тип char
и обратно.
Для всех программ, в которых используется пространство имен System
, доступны встроенные потоки, открывающиеся с помощью свойств Console.In
, Console.Out
и Console.Error
. В частности, свойство Console.Out
связано со стандартным потоком вывода. По умолчанию это поток вывода на консоль. Так, если вызывается метод Console.WriteLine()
, информация автоматически передается свойству Console.Out
. Свойство Console.In
связано со стандартным потоком ввода, который по умолчанию осуществляется с клавиатуры. А свойство Console.Error
связано со стандартным потоком сообщений об ошибках, которые по умолчанию также выводятся на консоль. Но эти потоки могут быть переадресованы на любое другое совместимое устройство ввода-вывода. Стандартные потоки являются символьными. Поэтому в эти потоки выводятся и вводятся из них символы.
Классы потоков
В среде .NET Framework определены классы как для байтовых, так и для символьных потоков. Но на самом деле классы символьных потоков служат лишь оболочками для превращения заключенного в них байтового потока в символьный, автоматически выполняя любые требующиеся преобразования типов данных. Следовательно, символьные потоки основываются на байтовых, хотя они и разделены логически.
Основные классы потоков определены в пространстве имен System.IO
. Для того чтобы воспользоваться этими классами, как правило, достаточно ввести приведенный ниже оператор в самом начале программы.
using System.IO;
Пространство имен System.IO
не указывается для консольного ввода-вывода потому, что для него определен класс Console
в пространстве имен System
.
Основным для потоков является класс System.IO.Stream
. Он представляет байтовый поток и является базовым для всех остальных классов потоков. Кроме того, он является абстрактным классом, а это означает, что получить экземпляр объекта класса Stream
нельзя. В классе Stream
определяется ряд операций со стандартными потоками, представленных соответствующими методами. В табл. 14.1 перечислен ряд наиболее часто используемых методов, определенных в классе Stream
.
Таблица 14.1. Некоторые методы, определенные в классе stream
Метод Описание
void Close() - Закрывает поток
void Flush() - Выводит содержимое потока на физическое устройство
int ReadByte() - Возвращает целочисленное представление следующего байта, доступного для ввода из потока. При обнаружении конца файла возвращает значение -1
int Read(byte[] buffer, int offset, int count) - Делает попытку ввести count байтов в массив
buffer, начиная с элемента buffer[offset]. Возвращает количество успешно введенных байтов