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

Как и прежде, путь обозначает имя открываемого файла, включая и полный путь к нему, а режим — порядок открытия файла. В то же время доступ обозначает конкретный способ доступа к файлу. В последнем случае указывается одно из значений, определяемых в перечислении FileAccess и приведенных ниже.

FileAccess.Read .    FileAccess.Write    FileAccess.ReadWrite

Например, в следующем примере кода файл test. dat открывается только для чтения.

FileStream fin = new FileStream("test.dat", FileMode.Open, FileAccess.Read);

По завершении работы с файлом его следует закрыть, вызвав метод 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.10;

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