Литмир - Электронная Библиотека
Содержание  
A
A

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

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

ПРИМЕЧАНИЕОператор using, рассматриваемый в главе 20, предоставляет еще один способ закрытия файла, который больше не нужен. Такой способ оказывается удобным во многих случаяхобращения с файлами, поскольку гарантирует закрытие ненужного больше файла простымисредствами. Но исключительно в целях демонстрации основ обращения с файлами, в томчисле и того момента, когда файл может быть закрыт, во всех примерах, представленныхв этой главе, используются явные вызовы метода Close().Чтение байтов из потока файлового ввода-вывода

В классе FileStream определены два метода для чтения байтов из файла:ReadByte() и Read(). Так, для чтения одного байта из файла используется методReadByte(), общая форма которого приведена ниже.int ReadByte()

Всякий раз, когда этот метод вызывается, из файла считывается один байт, которыйзатем возвращается в виде целого значения. К числу вероятных исключений, которыегенерируются при этом, относятся NotSupportedException (поток не открыт дляввода) и ObjectDisposedException (поток закрыт).

Для чтения блока байтов из файла служит метод Read(), общая форма котороговыглядит так.int Read(byte[ ] array, int offset, int count)

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

В приведенном ниже примере программы метод ReadByte() используется дляввода и отображения содержимого текстового файла, имя которого указывается в качестве аргумента командной строки. Обратите внимание на то, что в этой программепроверяется, указано ли имя файла, прежде чем пытаться открыть его./* Отобразить содержимое текстового файла. Чтобы воспользоваться этой программой, укажите имя того файла, содержимое которого требуется отобразить. Например, для просмотра содержимого файла TEST.CS введите в командной строке следующее: ShowFile TEST.CS*/using System;using System.IO;class ShowFile { static void Main(string[] args) { int i; FileStream fin; if(args.Length != 1) { Console.WriteLine("Применение: ShowFile Файл"); return; } try { fin = new FileStream(args[0], FileMode.Open); } catch(IOException exc) { Console.WriteLine("He удается открыть файл"); Console.WriteLine(exc.Message); return; // Файл не открывается, завершить программу } // Читать байты до конца файла. try { do { i = fin.ReadByte(); if(i != -1) Console.Write((char) i); } while(i != -1); } catch(IOException exc) { Console.WriteLine("Ошибка чтения файла"); Console.WriteLine(exc.Message); } finally { fin.Close(); } }}

Обратите внимание на то, что в приведенной выше программе применяются дваблока try. В первом из них перехватываются исключения, возникающие при вводе-выводе и способные воспрепятствовать открытию файла. Если произойдет ошибкаввода-вывода, выполнение программы завершится. В противном случае во второмблоке try будет продолжен контроль исключений, возникающих в операциях ввода-вывода. Следовательно, второй блок try выполняется только в том случае, если в переменной fin содержится ссылка на открытый файл. Обратите также внимание на то,что файл закрывается в блоке finally, связанном со вторым блоком try. Это означает, что независимо от того, как завершится цикл do-while (нормально или аварийноиз-за ошибки), файл все равно будет закрыт. И хотя в данном конкретном примереэто и так важно, поскольку программа все равно завершится в данной точке, преимущество такого подхода, вообще говоря, заключается в том, что файл закрывается в завершающем блоке finally в любом случае — даже если выполнение кода доступа кэтому файлу завершается преждевременно из-за какого-нибудь исключения.

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

Обратите внимание на то, что в данном варианте программы переменная finссылки на объект класса FileStream инициализируется пустым значением. Еслифайл удастся открыть в конструкторе класса FileStream, то значение переменнойfin окажется непустым, а иначе — оно так и останется пустым. Это очень важно, поскольку метод Close() вызывается внутри блока finally только в том случае, еслизначение переменной fin оказывается непустым. Подобный механизм препятствуетлюбой попытке вызвать метод Close() для переменной fin, когда она не ссылаетсяна открытый файл. Благодаря своей компактности такой подход часто применяетсяво многих примерах организации ввода-вывода, приведенных далее в этой книге. Следует, однако, иметь в виду, что он не пригоден в тех случаях, когда ситуацию, возникающую в связи с невозможностью открыть файл, нужно обрабатывать отдельно. Так,если пользователь неправильно введет имя файла, то на экран, возможно, придетсявывести приглашение правильно ввести имя файла, прежде чем входить в блок try,где осуществляется проверка правильности доступа к файлу.

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

Для записи байта в файл служит метод 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 байтов и более. Поэтому выводимые данные обычно буферизуются до тех пор,пока не появится возможность записать на диск сразу весь сектор.

94
{"b":"245736","o":1}