1629295407-c61bfe4caba98380ea3e7cdae6295416 (846200), страница 72
Текст из файла (страница 72)
Текст считывается до тех пор,пока пользователь не введет слово “стоп”. Здесь используется объект класса FileStream,помещенный в оболочку класса StreamWriter для вывода данных в файл./* Простая утилита "клавиатура-диск", котораядемонстрирует использование класса StreamWriter. */using System;using System.IO;class KtoD {public static void Main() {string str;FileStream fout;try {fout = new FileStream("test.txt", FileMode.Create);}catch(IOException exc) {Глава 14. Использование средств ввода-вывода389Console.WriteLine(exc.Message +"Не удается открыть файл.
");return;}StreamWriter fstr_out = new StreamWriter(fout);Console.WriteLine("Введите текст ('стоп' для завершения).");do {Console.Write(": ");str = Console.ReadLine();if(str != "стоп") {str = str + "\r\n"; // Добавляем символ// новой строки.try {fstr_out.Write(str);}catch(IOException exc) {Console.WriteLine(exc.Message +"Ошибка при работе с файлом.");return;}}}}} while(str != "стоп");fstr_out.Close();Иногда удобнее открывать файл с помощью класса StreamWriter. Для этогоиспользуйте один из следующих конструкторов:StreamWriter(string filename)StreamWriter(string filename, bool appendFlag)Здесь элемент filename означает имя открываемого файла, причем имя можетвключать полный путь к файлу.
Во второй форме используется параметр appendFlagтипа bool: если appendFlag равен значению true, выводимые данные добавляются вконец существующего файла. В противном случае заданный файл перезаписывается. Вобоих случаях, если файл не существует, он создается, а при возникновении ошибки вводавывода генерируется исключение типа IOException (также возможны и другиеисключения).Перед вами новая версия предыдущей утилиты “клавиатура-диск”, в которой дляоткрытия выходного файла используется класс StreamWriter.// Открытие файла с использованием класса StreamWriter.using System;using System.IO;class KtoD {public static void Main() {string str;StreamWriter fstr_out;// Открываем файл напрямую, используя// класс StreamWriter.try {fstr_out = new StreamWriter("test.txt");390Часть I.
Язык C#}}}catch(IOException exc) {Console.WriteLine(exc.Message +"Не удается открыть файл.");return;}Console.WriteLine("Введите текст ('стоп' для завершения).");do {Console.Write(": ");str = Console.ReadLine();if(str != "стоп") {str = str + "\r\n"; // Добавляем символ// новой строки.try {fstr_out.Write(str);}catch(IOException exc) {Console.WriteLine(exc.Message +"Ошибка при работе с файлом. ");return;}}} while(str != "стоп");fstr_out.Close();Использование класса StreamReaderЧтобы создать входной поток с ориентацией на обработку символов, поместитебайтовый поток в класс-оболочку StreamReader. В классе StreamReader определенонесколько конструкторов.
Чаще всего используется следующий конструктор:StreamReader(Stream stream)Здесь элемент stream означает имя открытого потока. Этот конструктор генерируетисключение типа ArgumentNullException, если поток stream имеет null-значение,и исключение типа ArgumentException, если поток stream не открыт для ввода. Послесоздания объект класса StreamReader автоматически преобразует байты в символы.Следующая программа создает простую утилиту “клавиатура-диск”, котораясчитывает текстовый файл test.txt и отображает его содержимое на экране. Такимобразом, эта программа представляет собой дополнение к утилите, представленной впредыдущем разделе./* Простая утилита "клавиатура-диск", котораядемонстрирует использование класса FileReader.
*/using System;using System.IO;class DtoS {public static void Main() {FileStream fin;Глава 14. Использование средств ввода-вывода391string s;try {fin = new FileStream("test.txt", FileMode.Open);}catch(FileNotFoundException exc) {Console.WriteLine(exc.Message +"Не удается открыть файл.");return;}StreamReader fstr_in = new StreamReader(fin);}}// Считываем файл построчно.while((s = fstr_in.ReadLine()) != null) {Console.WriteLine(s);}fstr_in.Close();Обратите внимание на то, как определяется конец файла. Если ссылка, возвращаемаяметодом ReadLine(), равна значению null, значит, конец файла достигнут.Как и в случае класса StreamWriter, иногда проще открыть файл, напрямуюиспользуя класс StreamReader.
Для этого обратитесь к этому конструктору:StreamReader(string filename)Здесь элемент filename означает имя открываемого файла, которое можетвключать полный путь к файлу. Указанный файл должен существовать. В противном случаегенерируется исключение типа FileNotFoundException. Если параметр filenameравен значению null, генерируется исключение типа ArgumentNullException, а еслион представляет собой пустую строку, — исключение типа ArgumentException.Перенаправление стандартных потоковКак упоминалось выше, такие стандартные потоки, как Console.In, можноперенаправлять. Безусловно, чаще всего они перенаправляются в какой-нибудь файл. Приперенаправлении стандартного потока входные и/или выходные данные автоматическинаправляются в новый поток. При этом устройства, действующие по умолчанию,игнорируются.
Благодаря перенаправлению стандартных потоков программа можетсчитывать команды из дискового файла, создавать системные журналы или даже считыватьвходные данные с сетевых устройств.Перенаправить стандартный поток можно двумя способами. Во-первых, привыполнении программы из командной строки можно использовать операторы “<” и “>”,чтобы перенаправить потоки Console.In и/или Console.Out, соответственно.Рассмотрим, например, следующую программу:using System;class Test {}public static void Main() {Console.WriteLine("Это тест.");}392Часть I. Язык C#При выполнении ее с помощью командной строкиTest > logтекстовая строка “Это тест.” будет записана в файл log. Входной поток можноперенаправить аналогичным способом. При перенаправлении входного потока важнопозаботиться о том, чтобы задаваемый источник входных данных содержал информацию,удовлетворяющую требованиям программы.
В противном случае программа зависнет.Операторы перенаправления “<” и “>” являются частью не языка C#, а операционнойсистемы. Таким образом, если среда поддерживает функцию перенаправления потоковввода-вывода (как это реализовано в Windows), вы сможете перенаправить стандартныевходные и выходные потоки, не внося изменений в программы. Однако существует ивторой способ, который позволяет перенаправлять стандартные потоки именнопрограммно. Для этого понадобятся следующие методы SetIn(), SetOut() иSetError(), которые являются членами класса Console:static void SetIn(TextReader input)static void SetOut(TextWriter output)static void SetError(TextWriter output)Таким образом, чтобы перенаправить входной поток, вызовите метод SetIn(),указав в качестве параметра желаемый поток.
Вы можете использовать любой входнойпоток, если он является производным от класса TextReader. Чтобы перенаправитьвыходной поток в файл, задайте FileStream-объект, помещенный в оболочкуStreamWriter-объекта. Пример перенаправления потоков проиллюстрирован следующейпрограммой:// Перенаправление потока Console.Out.using System;using System.IO;class Redirect {public static void Main() {StreamWriter log_out;try {log_out = new StreamWriter("logfile.txt");}catch(IOException exc) {Console.WriteLine(exc.Message +"Не удается открыть файл.");return;}// Направляем стандартный выходной поток в// системный журнал.Console.SetOut(log_out);Console.WriteLine("Это начало системного журнала.");for(int i=0; i<10; i++)Console.WriteLine(i);}}Console.WriteLine("Это конец системного журнала.");log_out.Close();Глава 14.
Использование средств ввода-вывода393При выполнении этой программы на экране не появится ни одного символа, но файлlogfile.txt будет иметь такое содержимое:Это начало системного журнала.0123456789Это конец системного журнала.При желании вы можете поэкспериментировать, перенаправляя другие встроенныепотоки ввода-вывода.Считывание и запись двоичных данныхДо сих пор мы считывали и записывали байты или символы, но эти операции вводавывода можно выполнять и с другими типами данных. Например, вы могли бы создатьфайл, содержащий int-, double- или short-значения. Для считывания и записидвоичных значений встроенных C#-типов используйте классы BinaryReader иBinaryWriter. Важно понимать, что эти данные считываются и записываются сиспользованием внутреннего двоичного формата, а не в текстовой форме, понятнойчеловеку.Класс BinaryWriterКласс BinaryWriter представляет собой оболочку для байтового потока, котораяуправляет записью двоичных данных.
Его наиболее употребительный конструктор имеетследующий вид:BinaryWriter(Stream outputStream)Здесь элемент outputStream означает поток, в который будут записыватьсяданные. Чтобы записать выходные данные в файл, можно использовать для этого параметраобъект, созданный классом FileStream. Если поток outputStream имеет nullзначение, генерируется исключение типа ArgumentNullException, а если потокoutputStream не открыт для записи, — исключение типа ArgumentException.В классе BinaryWriter определены методы, способные записывать значения всехвстроенных C#-типов (некоторые из них перечислены в табл. 14.5). Обратите внимание:значение типа string записывается с использованием внутреннего формата, которыйвключает спецификатор длины.
В классе BinaryWriter также определены стандартныеметоды Close() и Flush(), работа которых описана выше.Таблица 14.5. Методы вывода информации, определенные в классе BinaryWriterМетодОписаниеvoid Write(sbyte val)void Write(byte val)394Записывает byte-значение (со знаком)Записывает byte-значение (без знака)Часть I. Язык C#Окончание табл. 14.5МетодОписаниеvoid Write(byte[] buf)void Write(short val)Записывает массив byte-значенийЗаписывает целочисленное значение типа short (короткоецелое)Записывает целочисленное ushort -значение (короткое целоебез знака)Записывает целочисленное значение типа intЗаписывает целочисленное uint-значение (целое без знака)Записывает целочисленное значение типа long (длинноецелое)Записывает целочисленное ulong-значение (длинное целоебез знака)Записывает float-значениеЗаписывает double-значениеЗаписывает символЗаписывает массив символовЗаписывает string-значение с использованием еговнутреннего представления, которое включает спецификатордлиныvoid Write(ushort val)void Write(int val)void Write(uint val)void Write(long val)void Write(ulong val)voidvoidvoidvoidvoidWrite(float val)Write(double val)Write(char val)Write(char[] buf)Write(string val)Класс BinaryReaderКласс BinaryReader представляет собой оболочку для байтового потока, котораяуправляет чтением двоичных данных.