1629295407-c61bfe4caba98380ea3e7cdae6295416 (846200), страница 69
Текст из файла (страница 69)
Таким образом, символьные потоки построены на основебайтовых, несмотря на то, что они логически отделены друг от друга.Все классы потоков определены в пространстве имен System.IO. Чтобы иметьвозможность использовать эти классы, в начало программы необходимо включитьследующую инструкцию:using System.IO;Для ввода и вывода на консоль не нужно задавать пространство имен System.IO,поскольку класс Console определен в пространстве имен System.Класс StreamЦентральную часть потоковой C#-системы занимает класс System.IO.Stream.Класс Stream представляет байтовый поток и является базовым для всех остальныхпотоковых классов.
Этот класс также абстрактный, т.е. мы не можем создать его объект. Вклассе Stream определен набор стандартных потоковых операций. Наиболее применяемыеметоды, определенные в классе Stream, перечислены в табл. 14.1.Таблица 14.1. Некоторые методы класса StreamМетодОписаниеvoid Close()void Flush()int ReadByte()Закрывает потокЗаписывает содержимое потока в физическое устройствоВозвращает целочисленное представление следующегодоступного байта потока. При обнаружении конца файлавозвращает значение -1Делает попытку прочитать numBytes байт в массив buf,начиная с элемента buf[offset], возвращает количествоуспешно прочитанных байтовint Read(byte[] buf,int offset,int numBytes)long Seek (long offset,SeekOrigin origin)void WriteByte (byte b)void Write(byte[] buf,int offset,int numBytes)Устанавливает текущую позицию потока равной указанномузначению смещения от заданного начала отсчетаЗаписывает один байт в выходной потокЗаписывает поддиапазон размером numBytes байт измассива buf, начиная с элемента buf[offset]В общем случае при возникновении ошибки ввода-вывода методы, представленные втабл.
14.1, генерируют исключение типа IOException. При попытке выполнитьнекорректную операцию, например, записать данные в поток, предназначенный только длячтения, генерируется исключение типа NotSupportedException.Обратите внимание на то, что в классе Stream определены методы, которыесчитывают и записывают данные.
Однако не все потоки поддерживают все эти операции,поскольку возможен вариант, когда поток открывается только для чтения или только длязаписи. Кроме того, не все потоки поддерживают функцию установки в заданную позициюс помощью метода Seek(). Чтобы определить возможности потока, используйте одно илинесколько свойств класса Stream.
Они представлены в табл. 14.2. В этой таблице такжеописаны свойства Length и Position, которые содержат длину и текущую позициюпотока, соответственно.Глава 14. Использование средств ввода-вывода377Таблица 14.2. Свойства, определенные в классе StreamСвойствоОписаниеbool CanReadСвойство равно значению true, если из потока можно считывать данные.Это свойство предназначено только для чтенияСвойство равно значению true, если поток поддерживает функциюустановки в заданную позицию. Это свойство предназначено только длячтенияСвойство равно значению true, если в поток можно записывать данные.Это свойство предназначено только для чтенияСвойство содержит длину потока.
Это свойство предназначено только длячтенияСвойство представляет текущую позицию потока. Это свойство можно какчитать, так и устанавливатьbool CanSeekbool CanWritelong Lengthlong PositionБайтовые классы потоковИз класса Stream выведены такие байтовые классы потоков.Класс потокаОписаниеBufferedStreamЗаключает в оболочку байтовый поток и добавляет буферизацию.Буферизация во многих случаях увеличивает производительностьБайтовый поток, разработанный для файлового ввода-выводаБайтовый поток, который использует память для хранения данныхFileStreamMemoryStreamПрограммист может также вывести собственные потоковые классы. Однако дляподавляющего большинства приложений достаточно встроенных потоков.Символьные классы потоковЧтобы создать символьный поток, поместите байтовый поток в одну из символьныхпотоковых C#-оболочек.
В вершине иерархии символьных потоков находятся абстрактныеклассы TextReader и TextWriter. Класс TextReader предназначен для обработкиопераций ввода данных, а класс TextWriter — для обработки операций вывода данных.Методы, определенные этими двумя абстрактными классами, доступны для всех ихподклассов. Следовательно, они образуют минимальный набор функций ввода-вывода,который будут иметь все символьные потоки.В табл.
14.3 перечислены методы ввода данных, принадлежащие классуTextReader. В случае ошибки эти методы могут генерировать исключение типаIOException. (Некоторые методы могут также генерировать и другие типы исключений.)Особого внимания заслуживает метод ReadLine(), который считывает целую строкутекста, возвращая ее в качестве string-значения. Этот метод полезен при считываниивходных данных, которые содержат пробелы.Таблица 14.3. Методы ввода данных, определенные в классе TextReaderМетодОписаниеvoid Close()int Peek()Закрывает источник ввода данныхПолучает следующий символ из входного потока, но не удаляет его.Возвращает значение -1, если ни один символ не доступенВозвращает целочисленное представление следующего доступногосимвола из вызывающего объекта входного потока.
Приобнаружении конца файла возвращает значение -1int Read()378Часть I. Язык C#Окончание табл. 14.3МетодОписаниеint Read(char[] buf,int offset,int numChars)int ReadBlock(char[] buf,int offset,int numChars)string ReadLine()Делает попытку прочитать numChars символов в массив buf,начиная с элемента buf[offset], и возвращает количествоуспешно прочитанных символовДелает попытку прочитать numChars символов в массив buf,начиная с элемента buf[offset], и возвращает количествоуспешно прочитанных символовСчитывает следующую строку текста и возвращает ее какstring-значение.
При попытке прочитать признак концафайла возвращает null-значениеСчитывает все символы, оставшиеся в потоке, и возвращаетих как string-значениеstring ReadToEnd()В классе TextWriter определены версии методов Write() и WriteLine(),которые могут выводить данные всех встроенных типов. Приведем, например, тольконекоторые их перегруженные версии.МетодОписаниеvoidvoidvoidvoidЗаписывает значение типа intЗаписывает значение типа doubleЗаписывает значение типа boolЗаписывает значение типа string с последующимсимволом новой строкиЗаписывает значение типа uint с последующим символомновой строкиЗаписывает символ с последующим символом новой строкиWrite(int val)Write(double val)Write(bool val)WriteLine(string val)void WriteLine(uint val)void WriteLine(char val)Помимо методов Write() и WriteLine(), в классе TextWriter такжеопределены методы Close() и Flush():virtual void Close()virtual void Flush()Метод Flush() записывает все данные, оставшиеся в выходном буфере, нафизический носитель информации.
Метод Close() закрывает поток.Из классов TextReader и TextWriter выведен ряд символьно-ориентированныхпотоковых классов, в том числе и те, что перечислены в следующей таблице.Следовательно, эти потоковые классы используют методы и свойства, определенные вклассах TextReader и TextWriter.Потоковый классОписаниеStreamReaderПредназначен для чтения символов из байтового потока.Этот класс является оболочкой для байтового входногопотокаПредназначен для записи символов в байтовый поток. Этоткласс является оболочкой для байтового выходного потокаПредназначен для чтения символов из строкиПредназначен для записи символов в строкуStreamWriterSstringReaderStringWriterГлава 14.
Использование средств ввода-вывода379Двоичные потокиПомимо байтовых и символьных потоков, в C# определены два двоичных потоковыхкласса, которые можно использовать для прямого считывания и записи двоичных данных.Эти классы, которые называются BinaryReader и BinaryWriter, будут рассмотреныниже в этой главе в теме двоичного файлового ввода-вывода.Теперь, когда вы получили общее представление о C#-системе ввода-вывода, можнопереходить к детальному изучению этой темы, которую, пожалуй, стоит начать сконсольного ввода-вывода.Консольный ввод-вывод данныхКонсольный ввод-вывод данных реализуется посредством стандартных потоковConsole.In, Console.Out и Console.Error. Консольные классы ввода-выводаиспользовались, начиная с главы 2, поэтому вы уже с ними знакомы. Как вы убедитесьниже, они обладают и другими возможностями.Прежде всего, важно отметить, что большинство реальных C#-приложений являютсяне текстовыми, или консольными, а графическими программами или компонентами,которые опираются на оконный интерфейс, предназначенный для взаимодействия спользователем.
Таким образом, часть C#-системы ввода-вывода, которая связана сконсольным вводом-выводом данных, не относится к широко используемым средствам.Несмотря на то что текстовые программы — прекрасные учебные примеры короткихутилит и некоторых типов компонентов, они не годятся для большинства реальныхприложений.Считывание данных из консольного входного потокаПоток Console.In — экземпляр класса TextReader, поэтому для доступа к немуможно использовать методы и свойства, определенные в классе TextReader.
Однакообычно используют методы, определенные в классе Console, которые автоматическисчитывают значение свойства Console.In. В классе Console определено два методаввода информации: Read() и ReadLine().Метод Read() используется для считывания одного символа.static int Read()Метод Read() возвращает следующий символ, считанный с консоли. Он ожидает,пока пользователь не нажмет какую-нибудь клавишу, а затем возвращает результат.Считанный символ возвращается как значение типа int, которое должно быть приведено ктипу char. При возникновении ошибки метод Read() возвращает —1, а в случаенеудачного исхода операции генерирует исключение типа IOException.