3Обработка исключительных ситуаций при работе с файлами
Операции по открытию файлов могут завершиться неудачно, например, при ошибке в имени существующего файла или отсутствии свободного места на диске, поэтому рекомендуется всегда контролировать результаты этих операций. В случае непредвиденных ситуаций среда выполнения генерирует различные исключения, обработку которых следует предусмотреть в программе, например:
•FileNotFoundException, если файла с указанным именем в указанном каталоге не существует;
•DirectoryNotFoundException, если не существует указанный каталог;
•ArgumentEception, если неверно задан режим открытия файла;
•IOException, если файл не открывается из-за ошибок ввода-вывода.
Удобно обрабатывать наиболее вероятные ошибки раздельно, чтобы предоставить пользователю программы в выводимом сообщении наиболее точную информацию. В приведённом далее примере отдельно перехватывается ошибка в имени файла, а затем обрабатывается все остальные возможные ошибки:
try
{
FileStream f=new FileStream( @"d:\C#\text.txt", FileMode.Open, FileAccess.Read);
...//действия над файлом f.Close();
}
catch(FileNotFoundException e)
{
Console.WriteLine(e.Message);
Console.WriteLine("Проверьте правильность имени файла! "); return;
}
catch(Exception e)
{
Console.WriteLine("Error: " + e.Message); return;
}
При закрытии файла освобождаются все связанные с ним ресурсы, например, для файла, открытого для записи, в файл выгружается содержимое буфера. Поэтому рекомендуется всегда закрывать файлы после окончания работы, в особенности файлы, открытые для записи.
4Текстовые файлы
Символьные потоки - классы StreamWriter и StreamReader работают с Unicode-символами, следовательно, ими удобнее всего пользоваться для работы с файлами, предназначенными для восприятия человеком. Эти потоки являются наследниками классов TextWriter и TextReader соответственно. В таблицах 5 и 6 приведены основные элементы этих классов.
Произвольный доступ для текстовых файлов не поддерживается.
|
Таблица 5: Основные методы класса TextWriter |
|
|
|
|
Элемент |
Описание |
|
Close |
Закрыть файл и освободить связанные с ним ресурсы. Если в процессе |
|
записи используется буфер, он будет очищен |
||
|
||
|
Очистить все буферы для текущего файла и записать накопленные в них |
|
Flush |
данные в место их постоянного хранения. Сам файл при этом не |
|
|
закрывается |
|
NewLine |
Используется для задания последовательности символов, означающих |
|
начало новой строки. По умолчанию используется последовательность |
||
|
|
«возврат каретки» -«перевод строки» (\r\n) |
Write |
Записать фрагмент текста в поток |
WriteLine |
Записать строку в поток и перейти на другую строку |
|
|
|
Таблица 6: Основные методы класса TextReader |
|
|
Элемент |
Описание |
Peek |
Возвратить следующий символ, не изменяя позицию указателя в файле |
|
|
Read |
Считать данные из входного потока |
|
|
ReadBlock |
Считать из входного потока указанное пользователем количество |
|
символов и записать их в буфер, начиная с заданной позиции |
ReadLine |
Считать строку из текущего потока и возвратить ее как значение типа |
|
string. Пустая строка (null) означает конец файла(EOF) |
ReadToEnd |
Считать все символы до конца потока, начиная с текущей позиции, и |
|
возвратить считанные данные как одну строку типа string |
Примеры записи и чтения текстового файла
В данном примере создаётся текстовый файл, в который записываются 2 строки. Вторая формируется из преобразования численных значений переменных и поясняющего текста. Содержимое файла можно посмотреть в любом текстовом редакторе. Файл создается в том же каталоге, куда среда записывает исполняемый файл. По умолчанию это каталог
…\ConsoleApplication1\bin\Debug.
using System;
using System.Collections.Generic; using System.Linq;
using System.Text; using System.IO;
namespace file_app
{
class Program
{
static void Main(string[] args)
{
try
{
StreamWriter f = new StreamWriter("text.txt"); f.WriteLine("Запись в текстовый файл:"); double a = 12 / 234;
int b = 29;
f.WriteLine("a={0,6:C} b={1,2:X}", a, b); f.Close();
}
catch (Exception e)
{
Console.WriteLine("Error:" + e.Message); Console.ReadKey();
return;
}
}
}
}
Рисунок 3:
Файл, созданный в предыдущем примере выводится на экран.
using System;
using System.Collections.Generic; using System.Linq;
using System.Text; using System.IO;
namespace file_app
{
class Program
{
static void Main(string[] args)
{
try
{
StreamReader f = new StreamReader("text.txt"); string s = f.ReadToEnd(); Console.WriteLine(s);
f.Close(); Console.ReadKey(true);
}
catch (FileNotFoundException e)
{
Console.WriteLine(e.Message); Console.WriteLine("Проверьте правильность имени файла!"); Console.ReadKey();
return;
}
catch (Exception e)
{
Console.WriteLine("Error:" + e.Message); Console.ReadKey();
return;
}
}
}
}
В этой программе весь файл считывается за один прием с помощью метода ReadToEnd. Чаще возникает необходимость считывать файл построчно.
Такой пример приведен ниже. Каждая строка при выводе представляется номером.
using System;
using System.Collections.Generic; using System.Linq;
using System.Text; using System.IO;
namespace file_app
{
class Program
{
static void Main(string[] args)
{
try
{
StreamReader f = new StreamReader("text.txt"); string s;
long i = 0;
while ((s = f.ReadLine()) != null) Console.WriteLine("{0}: {1}", ++i, s);
f.Close();
}
catch (FileNotFoundException e)
{
Console.WriteLine(e.Message); Console.WriteLine("Проверьте правильность имени файла!"); Console.ReadKey();
return;
}
catch (Exception e)
{
Console.WriteLine("Error:" + e.Message); Console.ReadKey(); return;
}
}
}
}
Рисунок 4:
5Пример преобразования чисел, содержащихся в текстовом файле
В данном примере вычисляется сумма чисел в каждой строке.
На содержимое файла накладываются весьма строгие ограничения: числа должны быть разделены ровно одним пробелом, после последнего числа в строке пробела быть не должно, файл не должен заканчиваться символом перевода строки.
using System;
using System.Collections.Generic; using System.Linq;
using System.Text; using System.IO;
namespace file_app
{
class Program
{
static void Main(string[] args)
{
try
{
StreamReader f = new StreamReader("numbers.txt"); string s;
const int n = 20; int[] a = new int[n];