C# 4.0 полное руководство - 2011
Шрифт:
В этой главе речь пойдет о средствах консольного и файлового ввода-вывода. Следует, однако, сразу же предупредить, что система ввода-вывода в 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. 10. Для того чтобы воспользоваться этими классами, как правило, достаточно ввести приведенный ниже оператор в самом начале программы.
using System.10;
Пространство имен System. 10 не указывается для консольного ввода-вывода потому, что для него определен класс Console в пространстве имен System.
Класс Stream '
Основным для потоков является класс System. 10. Stream. Он представляет байтовый поток и является базовым для всех остальных классов потоков. Кроме того, он является абстрактным классом, а это означает, что получить экземпляр объекта класса Stream нельзя. В классе Stream определяется ряд операций со стандартными потоками, представленных соответствующими методами. В табл. 14.1 перечислен ряд наиболее часто используемых методов, определенных в классе Stream.
Таблица 14.1. Некоторые методы, определенные в классе stream
Метод
Описание
void Close
Закрывает
потокvoid Flush
Выводит содержимое потока на физическое устройство
int ReadByte
Возвращает целочисленное представление следующего байта, доступного для ввода из потока. При обнаружении конца файла возвращает значение -1
int Read(byte[] buffer,
Делает попытку ввести count байтов в массив
int offset, int count)
buffer, начиная с элемента buffer[offset]. Возвращает количество успешно введенных байтов
long Seek(long offset,
Устанавливает текущее положение в потоке по указан
SeekOrigin origin)
ному смещению offset относительно заданного начала отсчета origin. Возвращает новое положение в потоке
void WriteByte(byte value)
Выводит один байт в поток вывода
void Write(byte[]buffer,
Выводит подмножество count байтов из массива
int offset,
buffer, начиная с элемента buffer'i offset]. Воз
int count)
вращает количество выведенных байтов
Некоторые из методов, перечисленных в табл. 14.1, генерируют исключение IOException при появлении ошибки ввода-вывода. Если же предпринимается попытка выполнить неверную операцию, например вывести данные в поток, предназначенный только для чтения, то генерируется исключение NotSupportedException. Кроме того, могут быть сгенерированы и другие исключения — все зависит от конкретного метода.
Следует заметить, что в классе Stream определены методы для ввода (или чтения) и вывода (или записи) данных. Но не все потоки поддерживают обе эти операции, поскольку поток можно открывать только для чтения или только для записи. Кроме того, не все потоки поддерживают запрос текущего положения в потоке с помощью метода Seek . Для того чтобы определить возможности потока, придется воспользоваться одним, а то и несколькими свойствами класса Stream. Эти свойства перечислены в табл. 14.2 наряду со свойствами Length и Position, содержащими длину потока и текущее положение в нем.
Таблица 14.2. Свойства, определенные в классе Stream
Свойство
Описание
bool CanRead bool CanSeek
Принимает значение true, если из потока можно ввести данные. Доступно только для чтения
Принимает значение true, если поток поддерживает запрос текущего положения в потоке. Доступно только для чтения
Свойство
Описание