- •Лекция 11. Файлы в с# Основные понятия. Классы .Net для работы с файлами
- •Виды файлов
- •Алгоритм работы с файловыми потоками
- •Байтовые файлы (потоки)
- •Обработка исключительных ситуаций при работе с файлами
- •Текстовые файлы
- •Пример преобразования чисел, содержащихся в текстовом файле
- •Консольный ввод-вывод
- •Работа с каталогами и файлами
Обработка исключительных ситуаций при работе с файлами
Операции по открытию файлов могут завершиться неудачно, например, при ошибке в имени существующего файла или отсутствии свободного места на диске, поэтому рекомендуется всегда контролировать результаты этих операций. В случае непредвиденных ситуаций среда выполнения генерирует различные исключения, обработку которых следует предусмотреть в программе, например:
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; }
При закрытии файла освобождаются все связанные с ним ресурсы, например, для файла, открытого для записи, в файл выгружается содержимое буфера. Поэтому рекомендуется всегда закрывать файлы после окончания работы, в особенности файлы, открытые для записи.
Текстовые файлы
Символьные потоки - классы StreamWriter и StreamReader работают с Unicode-символами, следовательно, ими удобнее всего пользоваться для работы с файлами, предназначенными для восприятия человеком. Эти потоки являются наследниками классов TextWriter и TextReader соответственно. В таблицах 11.5 и 11.6 приведены основные элементы этих классов. Произвольный доступ для текстовых файлов не поддерживается.
Таблица 11.5 – Основные элементы класса TextWriter
Элемент Описание
Close Закрыть файл и освободить связанные с ним ресурсы. Если в процессе
записи используется буфер, он будет очищен
Flush Очистить все буферы для текущего файла и записать накопленные
в них данные в место их постоянного хранения. Сам файл при этом
не закрывается
NewLine Используется для задания последовательности символов, означающих
начало новой строки. По умолчанию используется последовательность
«возврат каретки» - «перевод строки» (\r\n)
Write Записать фрагмент текста в поток
WriteLine Записать строку в поток и перейти на другую строку
Таблица 11.6 - Основные элементы класса TextReader
Элемент Описание
Peek Возвратить следующий символ, не изменяя позицию указателя в файле
Read Считать данные из входного потока
ReadBlock Считать из входного потока указанное пользователем количество
символов и записать их в буфер, начиная с заданной позиции
ReadLine Считать строку из текущего потока и возвратить ее как значение
типа string. Пустая строка (null) означает конец файла(EOF)
ReadToEnd Считать все символы до конца потока, начиная с текущей позиции,
и возвратить считанные данные как одну строку типа string
Примеры записи и чтения текстового файла
В данном примере создается текстовый файл, в который записываются 2 строки. Вторая формируется из преобразования численных значений переменных и поясняющего текста. Содержимое файла можно посмотреть в любом текстовом редакторе. Файл создается в том же каталоге, куда среда записывает исполняемый файл. По умолчанию это каталог …\ConsoleApplication1\bin\Debug.
//ЗАПИСЬ В ТЕКСТОВЫЙ ФАЙЛ
using System;
using System.IO;
namespace ConsoleApplication1
{ class Class1
{ static void Main()
{ 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; } } }}
Файл, созданный в предыдущем примере выводиться на экран.
//ЧТЕНИЕ ТЕКСТОВОГО ФАЙЛА
using System;
using System.IO;
namespace ConsoleApplication1
{ class Class1
{ static void Main()
{ try
{ StreamReader f=new StreamReader ("text.txt");
string s=f.ReadToEnd();
Console.WriteLine(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; } } }}
В этой программе весь файл считывается за один прием с помощью метода ReadToEnd. Чаще возникает необходимость считывать файл построчно.
Такой пример приведен ниже. Каждая строка при выводе представляется номером.
//Построчное чтение текстового периода
using System;
using System.IO;
namespace ConsoleApplication1
{ class Class1
{ static void Main()
{ 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; } } }}