Содержание:
Теория
- Компонентный тип:
 - текстовые файлы (состоит из строк в некоторой кодировке)
 - бинарные файлы
 - Тип доступа к файлу:
 - Произвольный доступ: время доступа = Θ(1), компоненты данных имеют одинаковый размер
(байты в простейшем случае) - Последовательный доступ: компоненты данных имеют различный размер, для поиска 
i-го компонента необходимо считать предыдущийi-1компонент (пример: текстовые файлы) - Типы операций с файлами:
 - только для чтения
 - только для записи
 - чтение и запись
 - using System.IO;
 - using System.Text;
 - File – статический класс, операции с закрытыми файлами
 - FileMode – режим открытия файла
 - FileStream
 - StreamReader/StreamWriter – потоки для чтения-записи в текстовые файлы
 - BinaryReader/BinaryWriter — потоки для чтения-записи в двоичные файлы
 - Encoding – кодировки файлов
 - Классы 
FileиFileInfoоба предоставляют методы для создания, копирования, удаления, перемещения и открытия файлов. Они имеют очень похожие интерфейсы, разница лишь в том, чтоFileInfoобеспечивает методы экземпляра, тогда какFileобеспечивает методы static. - Разница в том, что если у вас будет небольшое количество операций, удобнее обращаться к статическим методам класса 
File. Если у вас будет много операций, более эффективно создать классFileInfoи получить доступ ко всем его методам экземпляра. - Класс 
Directoryпредоставляет статические методы, в то время какDirectoryInfoпредоставляет методы экземпляра. - У нас также есть класс 
Path, который предоставляет методы для работы со строкой, содержащей информацию о пути к файлу или каталогу. - FileMode.Create
 - FileMode.Open
 - FileMode.OpenOrCreate
 - FileMode.Append
 - Инструкция 
Usingобеспечивает автоматический вызов методаClose()при работе с классомFileStream. 
Классификация файлов
Операции с файлами
| 
с закрытыми файлами: открыть проверить существует ли удалить скопировать переименовать переместить  | 
С уже открытыми файлами: закрыть записать информацию читать информацию проверить, достигнут ли конец файла поиск n-й позиции  | 
Классы и пространства имен .NET
- 
Пространства имен:
 
В платформе .net есть пространство имен System.IO, именно там расположено множество классов для работы с файлами и каталогами.
Классы:
FileMode тип перечисленияОсновные методы класса File
- 
Operations with closed files:
 
using System.IO; // File.Exists("a.dat") Console.WriteLine(File.Exists("a.dat")); // true или false // File.Exists("d:\\a.dat") Console.WriteLine(File.Exists("d:\\a.dat")); // true или false // File.Exists(@"d:\a.dat") Console.WriteLine(File.Exists(@"d:\a.dat"); // true или false File.Delete("a.dat"); File.Copy("d:\\a.dat", "d:\\b.dat"); // будет создан файл b.dat, если он существует - возникнет исключение File.Copy("a.dat", @"d:\a.dat"); File.Move("a.dat", @"..\a.dat");  | 
Конструкция try .. catch
try { // код с возможным исключением } catch (Exception e) { // для обработки исключения }  | 
Пример:
try { var path = @"d:\a.dat"; var fs = new FileStream(path, FileMode.Open); ... } catch (FileNotFoundException e) { Console.WriteLine($"Файл с именем {e.FileName} не найден"); } catch (FileLoadException e) { Console.WriteLine($"К файлу с именем {e.FileName} невозможно получить доступ"); }  | 
ИнструкцияUsing
Пример работы с двоичными файлами:
using System.IO; // ... string path = @"Lesson14.dat"; // данные в файле: 1 2 3 4 var fs = new FileStream(path, FileMode.Open); var br = new BinaryReader(fs); var a=br.ReadInt32(); Console.WriteLine(a); // 1 var b = br.ReadInt32(); Console.WriteLine(b); // 2 var c = br.ReadInt32(); Console.WriteLine(c); // 3 fs.Close();  | 
Example:
var path = @"d:\a.dat"; using (var fs = new FileStream(path, FileMode.Create)) { fs.WriteByte(1); fs.WriteByte(2); fs.WriteByte(3); } using (var fs = new FileStream(path, FileMode.Open)) { Console.WriteLine(fs.ReadByte()); Console.WriteLine(fs.ReadByte()); Console.WriteLine(fs.ReadByte()); }  | 
Задания и лабораторные работы
Использование режима для создания файла и работы с ним без класса BinaryReader
Выполнить: Create a file with a name myFile.txt on your root folder d or c  (@"D:\myFile.txt"). Open created file and write there some entered string (don’t forget to convert it into a byte array -> Encoding.Default.GetBytes()). Then, read the file’s data and output it to the console window (by convering data again into string -> Encoding.Default.GetString(...)).
Создайте файл с именем myFile.txt в вашей корневой папке d или c (@"D:\myFile.txt"). Откройте созданный файл и запишите туда некоторую введенную строку (не забудьте преобразовать ее в байтовый массив -> Encoding.Default.GetBytes()). Затем считайте данные файла и выводите их в окно консоли (путем повторного преобразования данных в строку -> Encoding.Default.GetString(...)).
    
Примерный вывод:
Введите строку: Hello, world! Строка из файла: Hello, world!
[Название проекта: Lesson_14Task0, Название файла L14Task0.cs]
Обработка ошибок при работе с файлами. Оператор Try. Считывание данных из файла
Выполнить:
- Создайте программу для вывода содержимого файла в окно консоли (числа могут быть выведены через пробелы в строку). Вы должны использовать класс 
BinaryReader. - Скачайте файл L01.dat и поместите его в свою рабочую папку (
~/Lesson_14 Lab1/bin/Debug). В файле записано 15 целых чисел.. - Вы должны использовать инструкцию 
usingпри работе с уже открытым файлом. Тогда, независимо от успеха работы с открытым файлом, он всегда будет закрыт. - Используйте код для обработки исключений:
- Чтобы предотвратить «сбой» программы и не напугать пользователя, добавьте обработку исключений — блок 
try..catch. Операторusingдолжен находиться внутри блокаtry..catch. 
... try { ... } catch (IOException e) { Console.WriteLine($"Ошибка чтения из файла: {e.Message}"); }
 - Чтобы предотвратить «сбой» программы и не напугать пользователя, добавьте обработку исключений — блок 
 - Измените имя файла в программном коде на несуществующее. Запустите приложение и проверьте обработку исключения. Снова измените имя на правильное имя.
 - Здесь нет необходимости создавать методы.
 
using (var fs = new FileStream(path, FileMode.Create)) { ... }  | 
Примерный вывод:
Данные из файла: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 +++++++++++++ Данные из файла: Ошибка чтения из: Файл 'C:\Users\User\Documents\Visual Studio 2015\Projects\L14_Lab1\bin\Debug\L02.dat' не найден
 
[Название проекта: Lesson_14Lab1, название файла L14Lab1.cs]
✍ Алгоритм:
- Создайте новый проект с именем файла, как указано в задании.
 - Загрузите файл L01.dat и поместите его в свою рабочую папку  (
~/Lesson_14Lab1/bin/Debug). - Чтобы избежать необходимости постоянно упоминать класс 
Console, мы можем включить его объявление прямо в начале окна редактора: - Ниже этого кода подключите пространство имен 
System.IO— для работы с файлами: - В функции 
Mainобъявите переменную для хранения пути к файлу. Лучше использовать дословную строку (символ@): - Чтобы прочитать что-то из файла, сначала нужно открыть файл. Чтобы открыть файл, требуется указать путь к файлу в системе и режим.
 - Итак, нам нужно инициализировать новый экземпляр класса 
FileStreamс указанным путем и режимом. Будем использовать режимopen(для чтения из файла), потому что нам не нужно ничего записывать в файл. Переменнаяfsбудет хранить входной поток: - После этого нам нужно создать переменную (
br) — экземпляр классаBinaryReader, чтобы иметь возможность считывать данные из файла в виде двоичных значений: - Чтобы не возникало ошибки, если файл не существует или если имя файла написано неверно, мы будем использовать блок 
try...catch. Поместите добавленные инструкцииusingв блокtry: - Кроме того, внутри блока 
tryмы собираемся считывать байты или символы из файла и выводить их в консоль. Для этой цели будем использовать методPeekCharклассаBinaryReader: - В блоке 
catchмы собираемся распечатать сообщение в случае возникновения какой-либо ошибки, например, в случае неправильного имени файла: - В конце программного кода поместите метод 
ReadKey, чтобы не закрывать окно консоли при запуске программы в режиме отладки: - Нажмите клавишу 
F5, чтобы запустить программу в режиме отладки и проверить выходные данные. - Чтобы увидеть результат при возникновении ошибки, измените имя файла, например:
 - Нажмите клавишу 
F5, чтобы запустить программу в режиме отладки и проверить выходные данные. - Верните прежнее название файла
 - Загрузите файл 
.csна проверку. 
... using static System.Console; ...
using System.IO; ...
path = @"L01.dat";
using (var fs = new FileStream(path, FileMode.Open))
FileStream предоставляет поток (последовательность байтов) для ввода/считывания из файла; поддерживает как синхронные, так и асинхронные операции чтения и записи.... using (var br = new BinaryReader(fs))
... try { using (var fs = new FileStream(path, FileMode.Open)) using (var br = new BinaryReader(fs)) }
// в блоке try, после использования инструкций using: while (br.PeekChar() != -1) { var x = br.ReadInt32(); Write($"{x} "); }
BinaryReader класс считывает примитивные типы данных как двоичные значения в определенной кодировке.PeekChar метод возвращает следующий доступный символ или -1, если больше нет доступных символов или поток не поддерживает поиск.// under try block: catch (IOException e) { WriteLine($"Ошибка чтения из файла: {e.Message}"); }
IOException хранит исключение, которое генерируется при возникновении ошибки ввода-вывода.Message — это атрибут класса Exception, который возвращает сообщение об ошибке, объясняющее причину исключения, или пустую строку.
// после закрывающей скобки блока catch
ReadKey();
ReadKey ожидает ввода или нажатия клавиши клавиатуры. Нажатая клавиша отображается в окне консоли.path = @"L02.dat";
Выполнить: Скопируйте файл L01.dat для предыдущей лабораторной работы и вставьте его в папку текущего задания, пусть к файлу: (~/Lesson_14Task1/bin/Debug).
1. Создайте программу для вывода чисел в квадрате из файла в окно консоли (числа могут быть выведены через пробел в пределах одной строки), а также для вычисления количества четных цифр среди чисел. Вы должны использовать класс BinaryReader. Создайте программу, используя блок try..catch.
Указание: Здесь нет необходимости создавать методы.
     
Примерный вывод:
Квадраты чисел: 1 4 9 16 25 36 49 64 81 100 121 144 169 196 225 Количество четных: 7 +++++++++++++++ Ошибка чтения из файла: Файл 'c:\users\user\documents\visual studio 2015\Projects\L_14Task1\bin\Debug\L02.dat' не найден.
[Название проекта: Lesson_14Task1, название файла L14Task1.cs]
Выполнить:
- Загрузите файл в папку с проектом L01.dat. В файле записаны целые числа. Выведите эти числа в окно консоли по 
Nчисел в каждой строке (Nвводится (N > 0) и имеет значение по умолчанию =10). Необходимо использовать классBinaryReader. В случае если файл пустой выведите сообщение «пустой файл». - Может быть несколько блоков 
try..catch, и каждый из них может обрабатывать разные ошибки. Напишите свой код так, чтобы один блокtry..catchобрабатывал ошибки, возникающие при открытии файла, а другой блок обрабатывал ошибки, возникающие при работе с уже открытым файлом. - Тогда структура программы должна быть следующей:
 - Создайте метод с двумя параметрами для выполнения задачи. Сигнатура метода:
 - Проверьте, правильно ли работают блоки 
try..catch. Смоделируйте ошибку при работе с уже открытым файлом и ошибку с именем файла. После проверки верните предыдущий (правильный) код и закомментируйте неверный код. 
... try { using ( ... ) using ( ... ) { try { // работа с открытым файлом... } catch { // обработка ошибки при работе с уже открытым файлом } } catch { // обработка ошибки, связанной с открытием файла }  | 
static void PrintFileInRows(string path, int N=10)  | 
Примерный вывод:
Введите N: 3 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 +++++++++++++ Введите N: 3 Ошибка чтения из файла: Файл 'c:\users\user\documents\visual studio 2015\Projects\L_14Lab2\bin\Debug\L02.dat' не найден. +++++++++++++ Введите N: 3 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Ошибка работы с данными файла: Чтение после конца потока невозможно.
 
[Название проекта: Lesson_14Lab2, название файла L14Lab2.cs]
✍ Алгоритм:
- Создайте новый проект с именем и именем файла, как указано в задаче.
 - Загрузите файл L01.dat и разместите его в рабочей папке проекта (
~/Lesson_14Lab2/bin/Debug). - Чтобы не печатать постоянно класс 
Console, мы можем включить его объявление прямо в начале окна редактора: - Подключите пространство имен <код>System.IO для работы с файлами:
 - В функции 
Mainобъявите переменную для хранения пути к файлу. Лучше использовать дословную строку (символ@): - Мы собираемся вывести числа из файла в нескольких строках: <код> N чисел в каждой строке. В функции main нам нужно запросить пользователя число <код>N:
 - Затем необходимо объявить метод с именем 
PrintFileInRowsс двумя параметрами — путь к файлу и количествоN: - Чтобы прочитать что-то из файла, сначала нужно открыть файл. Но в соответствии с требованием задачи у нас должно быть два блока 
try..catch, один из них обрабатывает ошибки, возникающие при открытии файла, а другой блок обрабатывает ошибки, возникающие при работе с уже открытым файлом. - Итак, давайте сначала создадим блоки 
try..catch, а затем поместим в них остальной код: - Чтобы открыть файл, необходимо указать путь к файлу в вашей системе и режим открытия — как операционная система должна открывать файл. Поместите следующий код после открытой фигурной скобки первого блока 
try..catch: - После этого мы собираемся работать с файлом, это означает, что мы будем считывать некоторые данные из файла и что-то с ними делать. Итак, нам нужно создать переменную (
br) как экземпляр классаBinaryReader, чтобы иметь возможность считывать данные из файла в виде двоичных значений. Следующий код должен быть помещен во второй блокtry..catch, который находится внутри инструкцииusing: - В соответствии с требованиями задачи мы должны вывести сообщение «пустой файл», если в файле нет никаких данных. Лучше использовать метод 
PeekChar, который возвращает-1, если файл пуст: - После этого мы будем считывать числа одно за другим из файла и выводить их в консоль. Необходимо выводить <код>N чисел в каждой строке. Используем счетчик 
i, чтобы подсчитать, сколько чисел мы уже прочитали. Если количество считанных чисел равноN, то мы перейдем к следующей строке: - В первом блоке 
catchмы собираемся распечатать сообщение в случае возникновения какой-либо ошибки при работе с файлом: - Во втором блоке 
catchмы собираемся распечатать сообщение в случае возникновения какой-либо ошибки при открытии файла: - В конце кода программы поместите метод 
ReadKey, чтобы не закрывать окно консоли при запуске программы в режиме отладки: - Нажмите F5, чтобы запустить программу в режиме отладки и проверить выходные данные.
 - Чтобы увидеть результат при возникновении ошибки, измените имя файла, например:
 - Нажмите F5, чтобы запустить программу в режиме отладки и проверить выходные данные.
 - Верните правильное имя файлу.
 - Чтобы увидеть результат при возникновении ошибки во время работы с файлом, добавьте следующую строку после инструкции while:
 - Нажмите F5, чтобы запустить программу в режиме отладки и проверить выходные данные.
 - Прокомментируйте неправильную строку кода.
 - Загрузите файл 
.csв систему moodle. 
... using static System.Console; ...
using System.IO; ...
path = @"L01.dat";
... WriteLine($"Введите N:"); var n = .Parse(ReadLine());
// после закрывающей фигурной скобки основной функции static PrintFileInRows( path, n = 10) { ... }
void.// в фигурных скобках метода try { /* здесь будет код, в котором могут возникать ошибки при открытии файла*/ { try { /* здесь будет код, в котором могут возникать ошибки при работе с уже открытым файлом*/ } catch (IOException e) { // сообщение об ошибке при работе с файлом } } } catch (IOException e) { // сообщение об ошибке при открытии файла } }
using ( f = File.Open(path, FileMode.Open)) { ... }
// после открытой фигурной скобки оператора using try { br = new BinaryReader(f);
if (br.PeekChar() == -1) { WriteLine("пустой файл"); }
// после предыдущего оператора if i = 0; while (br.PeekChar() != -1) { if (i >= n) { WriteLine(); i = 0; } Write(br.ReadInt32() + " "); i++; }
// within the first catch block: catch (IOException e) { WriteLine($"Ошибка работы с файлом: {e.Message}"); }
IOException хранит исключение, которое генерируется при возникновении ошибки ввода-вывода.Message — это атрибут класса Exception, который возвращает сообщение об ошибке, объясняющее причину исключения, или пустую строку («»).// в пределах первого блока catch: catch (IOException e) { Console.WriteLine($"Ошибка считывания из файла: {e.Message}"); }
// после закрывающей скобки блока фиксации:
ReadKey();
ReadKey получает следующий символ или функциональную клавишу, нажатую пользователем. Нажатая клавиша отображается в окне консоли.path = @"L02.dat";
// после закрытия фигурной скобки оператора while: WriteLine(br.ReadInt32());
Выполнить: Загрузите файл Task02.dat и вставьте его в папку с проектом:  (~/Lesson_14Task2/bin/Debug). В файле записаны целые числа. Создайте программу, которая сначала выведет эти числа в окно консоли, а после этого подсчитает количество чисел, которые меньше, чем их сосед слева (меньше, чем предыдущее число в последовательности чисел).
Указание 1: Создайте метод для печати данных из файла:
static void PrintData(string path)  | 
Указание 2: Создайте метод для вывода количества чисел, меньших, чем их сосед слева:
static int CountLessThanLeft(string path)  | 
Указание 3: Возможно, потребуется использовать определенную кодировку символов при чтении из файла:
using (var fs = new FileStream(path, FileMode.Open)) using (var br = new BinaryReader(fs, Encoding.ASCII))  | 
Указание 4: Может быть несколько блоков try..catch, и каждый из них может обрабатывать разные ошибки. Напишите свой код так, чтобы один блок try..catch обрабатывал ошибки, возникающие при открытии файла, а другой блок обрабатывал ошибки, возникающие при работе с уже открытым файлом.
Тогда структура программы должна быть следующей:
... try { using ( ... ) using ( ... ) { try { //работа с открытым файлом... } catch { // обработка ошибки при работе с уже открытым файлом } } catch { // обработка ошибки открытия файла }  | 
Указание 5: Проверьте, правильно ли работают блоки try..catch. Смоделируйте ошибку при работе с уже открытым файлом и ошибку с именем файла. После проверки верните предыдущий (правильный) код и закомментируйте неправильный.
Примерный вывод:
Числа в файле: -35 25 28 -37 13 -9 -24 12 -35 37 -24 20 29 -11 -45 -8 43 12 12 44 Количество чисел, меньших, чем их левый сосед: 8 +++++++++++++++ Числа в файле: -35 25 28 -37 13 -9 -24 12 -35 37 -24 20 29 -11 -45 -8 43 12 12 44 Ошибка работы с файлом: Чтение после конца потока невозможно. Количество чисел, меньших, чем их левый сосед: 8 +++++++++++++++
[Название проекта: Lesson_14Task2, Название файла L14Task2.cs]