Выбрать главу

Для записи байта в файл служит метод WriteByte(). Ниже приведена его про стейшая форма. void WriteByte(byte value)

Этот метод выполняет запись в файл байта, обозначаемого параметром value. Если базовый поток не открывается для вывода, то генерируется исключение NotSupportedException. А если поток закрыт, то генерируется исключение ObjectDisposedException.

Для записи в файл целого массива байтов может быть вызван метод Write(). Ниже приведена его общая форма. void Write(byte[] array, int offset, int count)

В методе Write() предпринимается попытка записать в файл количество count байтов из массива array, начиная с элемента array[offset]. Он возвращает количе ство байтов, успешно записанных в файл. Если во время записи возникает ошибка, то генерируется исключение IOException. А если базовый поток не открывается для вы вода, то генерируется исключение NotSupportedException. Кроме того, может быть сгенерирован ряд других исключений.

Вам, вероятно, известно, что при выводе в файл выводимые данные зачастую запи сываются на конкретном физическом устройстве не сразу. Вместо этого они буфери зуются на уровне операционной системы до тех пор, пока не накопится достаточный объем данных, чтобы записать их сразу одним блоком. Благодаря этому повышается эффективность системы. Так, на диске файлы организованы по секторам величиной от 128 байтов и более. Поэтому выводимые данные обычно буферизуются до тех пор, пока не появится возможность записать на диск сразу весь сектор.

Но если данные требуется записать на физическое устройство без предварительно го накопления в буфере, то для этой цели можно вызвать метод Flush. void Flush()

При неудачном исходе данной операции генерируется исключение IOException. Если же поток закрыт, то генерируется исключение ObjectDisposedException.

По завершении вывода в файл следует закрыть его с помощью метода Close(). Этим гарантируется, что любые выведенные данные, оставшиеся в дисковом буфе ре, будут записаны на диск. В этом случае отпадает необходимость вызывать метод Flush() перед закрытием файла.

Ниже приведен простой пример программы, в котором демонстрируется порядок записи данных в файл. // Записать данные в файл. using System; using System.IO; class WriteToFile { static void Main(string[] args) { FileStream fout = null; try { // Открыть выходной файл. fout = new FileStream("test.txt", FileMode.CreateNew); // Записать весь английский алфавит в файл. for(char с = 'А'; с <= 'Z'; C++) fout.WriteByte((byte) с); } catch(IOException exc) { Console.WriteLine("Ошибка ввода-вывода:\n" + exc.Message); } finally { if (fout != null) fout.Close(); } } }

В данной программе сначала создается выходной файл под названием test.txt с помощью перечисляемого значения FileMode.CreateNew. Это означает, что файл с таким же именем не должен уже существовать. (В противном случае генерируется исключение IOException.) После открытия выходного файла в него записываются прописные буквы английского алфавита. По завершении данной программы содер жимое файла test.txt оказывается следующим. ABCDEFGHIJKLMNOPQRSTUVWXYZ Использование класса FileStream для копирования файла

Преимущество байтового ввода-вывода средствами класса FileStream заключает ся, в частности, в том, что его можно применить к файлам практически любого типа, а не только к текстовым файлам. В качестве примера ниже приведена программа, по зволяющая копировать файл любого типа, в том числе исполняемый. Имена исходно го и выходного файлов указываются в командной строке. /* Копировать файл. Чтобы воспользоваться этой программой, укажите имена исходного и выходного файлов. Например, для копирования файла FIRST.DAT в файл SECOND.DAT введите в командной строке следующее: CopyFile FIRST.DAT SECOND.DAT */ using System; using System.IO; class CopyFile { static void Main(string[] args) { int i; FileStream fin = null; FileStream fout = null; if(args.Length != 2) { Console.WriteLine("Применение: CopyFile Откуда Куда"); return; } try { // Открыть файлы. fin = new FileStream(args[0], FileMode.Open); fout = new FileStream(args[1], FileMode.Create); // Скопировать файл. do { i = fin.ReadByte(); if(i != -1) fout.WriteByte((byte)i); } while (i != —1); } catch(IOException exc) { Console.WriteLine("Ошибка ввода-вывода:\n" + exc.Message); } finally { if(fin != null) fin.Close(); if(fout != null) fout.Close(); } } } Символьный ввод-вывод в файл

Несмотря на то что файлы часто обрабатываются побайтово, для этой цели можно воспользоваться также символьными потоками. Преимущество символьных потоков заключается в том, что они оперируют символами непосредственно в уникоде. Так, если требуется сохранить текст в уникоде, то для этого лучше всего подойдут именно символьные потоки. В целом, для выполнения операций символьного ввода-вывода в файлы объект класса FileStream заключается в оболочку класса StreamReader или StreamWriter. В этих классах выполняется автоматическое преобразование байтового потока в символьный и наоборот.

Не следует, однако, забывать, что на уровне операционной системы файл представ ляет собой набор байтов. И применение класса StreamReader или StreamWriter никак не может этого изменить.

Класс StreamWriter является производным от класса TextWriter, а класс StreamReader — производным от класса TextReader. Следовательно, в классах StreamReader и StreamWriter доступны методы и свойства, определенные в их ба зовых классах. Применение класса StreamWriter

Для создания символьного потока вывода достаточно заключить объект клас са Stream, например FileStream, в оболочку класса StreamWriter. В классе StreamWriter определено несколько конструкторов. Ниже приведен едва ли не са мый распространенный среди них: StreamWriter(Stream поток)

где поток обозначает имя открытого потока. Этот конструктор генерирует исклю чение ArgumentException, если поток не открыт для вывода, а также исключение ArgumentNullException, если поток оказывается пустым. После создания объекта класс StreamWriter выполняет автоматическое преобразование символов в байты.

Ниже приведен простой пример сервисной программы ввода с клавиатуры и выво да на диск набранных текстовых строк, сохраняемых в файле test.txt. Набираемый тест вводится до тех пор, пока в нем не встретится строка "стоп". Для символьного вы вода в файл в этой программе используется объект класса FileStream, заключенный в оболочку класса StreamWriter. // Простая сервисная программа ввода с клавиатуры и вывода на диск, // демонстрирующая применение класса StreamWriter. using System; using System.IO; class KtoD { static void Main() { string str; FileStream fout; // Открыть сначала поток файлового ввода-вывода. try { fout = new FileStream("test.txt", FileMode.Create); } catch(IOException exc) { Console.WriteLine("Ошибка открытия файла:\n" + exc.Message); return; } // Заключить поток файлового ввода-вывода в оболочку класса StreamWriter. StreamWriter fstr_out = new StreamWriter(fout); try { Console.WriteLine("Введите текст, а по окончании — 'стоп'."); do { Console.Write(": "); str = Console.ReadLine(); if(str != "стоп") { str = str + "\r\n"; // добавить новую строку fstr_out.Write(str); } } while(str != "стоп"); } catch(IOException exc) { Console.WriteLine("Ошибка ввода-вывода:\n" + exc.Message); } finally { fstr_out.Close (); } } }

В некоторых случаях файл удобнее открывать средствами самого класса StreamWriter. Для этого служит один из следующих конструкторов: StreamWriter(string путь) StreamWriter(string путь, bool append)

где путь — это имя открываемого файла, включая полный путь к нему. Если во вто рой форме этого конструктора значение параметра append равно true, то выводи мые данные присоединяются в конец существующего файла. В противном случае эти данные перезаписывают содержимое указанного файла. Но независимо от формы конструктора файл создается, если он не существует. При появлении ошибок ввода- вывода в обоих случаях генерируется исключение IOException. Кроме того, могут быть сгенерированы и другие исключения.

Ниже приведен вариант представленной ранее сервисной программы ввода с кла виатуры и вывода на диск, измененный таким образом, чтобы открывать выходной файл средствами самого класса StreamWriter. // Открыть файл средствами класса StreamWriter. using System; using System.IO; class KtoD { static void Main() { string str; StreamWriter fstr_out = null; try { // Открыть файл, заключенный в оболочку класса StreamWriter. fstr_out = new StreamWriter("test.txt"); Console.WriteLine("Введите текст, а по окончании — 'стоп'."); do { Console.Write(" : "); str = Console.ReadLine(); if(str != "стоп") { str = str + "\r\n"; // добавить новую строку fstr_out.Write(str); } } while(str != "стоп"); } catch(IOException exc) { Console.WriteLine("Ошибка ввода-вывода:\n" + exc.Message); } finally { if(fstr_out != null) fstr_out.Close(); } } } Применение класса StreamReader

Для создания символьного потока ввода достаточно заключить байтовый поток в оболочку класса StreamReader. В классе StreamReader определено несколько кон структоров. Ниже приведен наиболее часто используемый конструктор: StreamReader(Stream поток)

где поток обозначает имя открытого потока. Этот конструктор генерирует исключе ние ArgumentNullException, если поток оказывается пустым, а также исключение ArgumentException, если поток не открыт для ввода. После своего создания объект класса StreamReader выполняет автоматическое преобразование байтов в символы. По завершении ввода из потока типа StreamReader его нужно закрыть. При этом за крывается и базовый поток.

В приведенном ниже примере создается простая сервисная программа ввода с дис ка и вывода на экран содержимого текстового файла test.txt. Она служит дополне нием к представленной ранее сервисной программе ввода с клавиатуры и вывода на диск. // Простая сервисная программа ввода с диска и вывода на экран, // демонстрирующая применение класса StreamReader. using System; using System.IO; class DtoS { static void Main() { FileStream fin; string s; try { fin = new FileStream("test.txt", FileMode.Open); } catch(IOException exc) { Console.WriteLine("Ошибка открытия файла:\n" + exc.Message); return; } StreamReader fstr_in = new StreamReader(fin); try { while((s = fstr_in.ReadLine()) != null) { Console.WriteLine(s); } } catch(IOException exc) { Console.WriteLine("Ошибка ввода-вывода:\n" + exc.Message); } finally { fstr_in.Close(); } } }