Шаг 292.
Язык программирования C#. Начала.
Немного о разном. Работа с файлами
На этом шаге мы рассмотрим основные принципы работы с файлами.
Очень часто данные в программу передаются с помощью файлов. Вывод результатов в файл также является удобным и популярным способом реализации программы. Начиная с этого шага, речь
пойдет о том, как в C# реализуется работа с файлами. Более конкретно, мы обсудим вопросы, связанные со считыванием информации из файла и записью информации в файл.
Важным элементом в концепции файлового ввода и вывода данных является такое понятие, как поток.
Не следует путать потоки данных с потоками, которые мы рассматривали в шагах, посвященных многопоточному программированию. В английском языке термин thread используется для
обозначения кода, выполняемого одновременно с другими блоками кода. Термин stream используется для обозначения последовательности данных. Оба термина на русский язык обычно
переводят как поток, но это разные потоки. В данном случае мы говорим о потоках, которым соответствует англоязычный термин stream.
Под потоком мы будем подразумевать некоторую упорядоченную последовательность данных. Технически такая последовательность может рассматриваться как набор битов (нулей и единиц).
Обрабатываются такие последовательности блоками. Как мы знаем, блок из восьми битов называется байтом. Соответственно, байтовый поток - это поток, который обрабатывается на уровне байтов
(то есть байтовыми блоками). Есть и символьные потоки - в них данные обрабатываются блоками по два байта, и каждый такой блок интерпретируется как символ.
Напомним, что в языке C# для хранения символьных значений выделяется 16 бит, или 2 байта.
Для работы с потоками существуют специальные классы. Абстрактный класс Stream из пространства имен System.IO является базовым для других классов, предназначенных для
работы с потоками. В частности, для реализации файлового ввода/вывода используется класс FileStream. Этот класс предназначен для работы с байтовыми потоками. У класса есть несколько
конструкторов, которые позволяют создать поток, связанный с файлом. Например, первым аргументом конструктору класса можно передать текст с названием файла (полным путем к файлу), а второй
аргумент при этом определяет режим доступа к файлу. Для определения режима доступа к файлу используют одну из констант перечисления FileMode:
- Константа Append означает режим, при котором новые данные добавляются в конец файла.
- Константа Create означает, что будет создан новый файл. Если файл с указанным именем уже существует, то он будет заменен новым.
- Константа CreateNew используется, если нужно создать новый файл. При этом не допускается, чтобы файл с указанным именем уже существовал.
- Константа Open означает, что открывается уже существующий файл.
- Если использована константа OpenOrCreate, то открывается существующий файл, а если файла нет, то он создается.
- Константа Truncate означает, что открывается существующий файл, при этом для файла устанавливается нулевой размер.
Попытка открыть файл может привести к ошибке. Например, если файл отсутствует, генерируется ошибка класса FileNotFoundException. При отсутствии прав доступа к файлу генерируется
исключение класса SecurityException. При ошибке ввода/вывода генерируется исключение IOException и так далее. Поэтому при создании потока на основе файла обычно применяется
обработка исключительных ситуаций.
Создание потока на основе файла открывает возможность для записи данных в файл и считывания данных из файла. В принципе, можно ограничиться лишь одной операцией (считывание данных или
запись данных). Сделать это можно с помощью третьего аргумента, который передается конструктору класса FileStream. Это константа из перечисления FileAccess:
- Read (только чтение),
- Write (только запись) или
- ReadWrite (чтение и запись).
Объекты класса FileStream имеют полезные свойства и методы. Например, длину потока в байтах можно узнать с помощью свойства Length. Свойства CanRead и
CanWrite позволяют определить доступность потока для чтения и записи соответственно. Позиция в потоке определяется с помощью свойства Position. Есть и другие свойства.
Среди методов можно выделить такие:
- Метод ReadByte() позволяет считать байт из потока. Считанный байт возвращается результатом метода. Если достигнут конец файла, результатом метода возвращается значение -1.
- Метод Read() считывает байты из потока и записывает их в байтовый массив. Первым аргументом метод получает байтовый массив, в который записываются байты. Второй аргумент
метода определяет позицию в массиве, начиная с которого копируются байты. Третий аргумент метода определяет количество байтов, считываемых из потока.
- Метод WriteByte() позволяет записать байт (аргумент метода) в файловый поток (то есть в файл) в текущую позицию.
- Метод Write() позволяет записать байты из массива (первый аргумент метода) в файловый поток (то есть в файл). Вторым аргументом методу передается индекс элемента в массиве,
начиная с которого копируются байты. Третий аргумент метода - количество байтов, записываемых в поток.
- Метод Close() используется для закрытия потока. При завершении работы с потоком необходимо вызывать этот метод.
- Метод CopyTo() позволяет копировать содержимое одного потока (из объекта которого вызывается метод) в другой поток (аргумент метода).
- Метод Flush() вызывается в случае, если необходимо записать буферизированные данные в поток.
- Метод Seek() используется для установки текущего положения в потоке для ввода/вывода данных. Вторым аргументом методу передается константа из перечисления
SeekOrigin (возможные значения Begin, Current и End), которая определяет "отправную точку" для определения позиции в потоке. Позиция в потоке определяется смещением по
отношению к "отправной точке". Значение смещения (в байтах) передается первым аргументом методу.
На следующем шаге мы рассмотрим пример использования объекта FileStream.
Предыдущий шаг
Содержание
Следующий шаг