СДЕЛАЙТЕ СВОИ УРОКИ ЕЩЁ ЭФФЕКТИВНЕЕ, А ЖИЗНЬ СВОБОДНЕЕ

Благодаря готовым учебным материалам для работы в классе и дистанционно

Скидки до 50 % на комплекты
только до

Готовые ключевые этапы урока всегда будут у вас под рукой

Организационный момент

Проверка знаний

Объяснение материала

Закрепление изученного

Итоги урока

Работа с файловой системой

Категория: Информатика

Нажмите, чтобы узнать подробности

Просмотр содержимого документа
«Работа с файловой системой»

Работа с файловой системой

Работа с файловой системой

 Большинство задач в программировании так или иначе связаны с работой с файлами и каталогами. Нам может потребоваться прочитать текст из файла или наоборот произвести запись, удалить файл или целый каталог, не говоря уже о более комплексных задачах, как например, создание текстового редактора и других подобных задачах.
  • Большинство задач в программировании так или иначе связаны с работой с файлами и каталогами. Нам может потребоваться прочитать текст из файла или наоборот произвести запись, удалить файл или целый каталог, не говоря уже о более комплексных задачах, как например, создание текстового редактора и других подобных задачах.
 Фреймворк .NET предоставляет большие возможности по управлению и манипуляции файлами и каталогами, которые по большей части сосредоточены в пространстве имен System.IO. Классы, расположенные в этом пространстве имен (такие как Stream, StreamWriter, FileStream и др.), позволяют управлять файловым вводом-выводом.
  • Фреймворк .NET предоставляет большие возможности по управлению и манипуляции файлами и каталогами, которые по большей части сосредоточены в пространстве имен System.IO. Классы, расположенные в этом пространстве имен (такие как Stream, StreamWriter, FileStream и др.), позволяют управлять файловым вводом-выводом.
  Работа с дисками  Работу с файловой системой начнем с самого верхнего уровня - дисков. Для представления диска в пространстве имен System.IO имеется класс DriveInfo.

Работа с дисками

  • Работу с файловой системой начнем с самого верхнего уровня - дисков. Для представления диска в пространстве имен System.IO имеется класс DriveInfo.
Этот класс имеет статический метод GetDrives(), который возвращает имена всех логических дисков компьютера. Также он предоставляет ряд полезных свойств: AvailableFreeSpace: указывает на объем доступного свободного места на диске в байтах DriveFormat: получает имя файловой системы DriveType: представляет тип диска IsReady: готов ли диск (например, DVD-диск может быть не вставлен в дисковод)

Этот класс имеет статический метод GetDrives(), который возвращает имена всех логических дисков компьютера. Также он предоставляет ряд полезных свойств:

  • AvailableFreeSpace: указывает на объем доступного свободного места на диске в байтах
  • DriveFormat: получает имя файловой системы
  • DriveType: представляет тип диска
  • IsReady: готов ли диск (например, DVD-диск может быть не вставлен в дисковод)
Name: получает имя диска RootDirectory: возвращает корневой каталог диска TotalFreeSpace: получает общий объем свободного места на диске в байтах TotalSize: общий размер диска в байтах VolumeLabel: получает или устанавливает метку тома
  • Name: получает имя диска
  • RootDirectory: возвращает корневой каталог диска
  • TotalFreeSpace: получает общий объем свободного места на диске в байтах
  • TotalSize: общий размер диска в байтах
  • VolumeLabel: получает или устанавливает метку тома
 Получим имена и свойства всех дисков на компьютере:
  • Получим имена и свойства всех дисков на компьютере:
Консольный вывод:

Консольный вывод:

Работа с каталогами Для работы с каталогами в пространстве имен System.IO предназначены сразу два класса: Directory и DirectoryInfo.

Работа с каталогами

  • Для работы с каталогами в пространстве имен System.IO предназначены сразу два класса: Directory и DirectoryInfo.
Класс Directory Статический класс Directory предоставляет ряд методов для управления каталогами. Некоторые из этих методов: CreateDirectory(path): создает каталог по указанному пути path Delete(path): удаляет каталог по указанному пути path Exists(path): определяет, существует ли каталог по указанному пути path. Если существует, возвращается true, если не существует, то false GetCurrentDirectory(): получает путь к текущей папке GetDirectories(path): получает список подкаталогов в каталоге path

Класс Directory

Статический класс Directory предоставляет ряд методов для управления каталогами. Некоторые из этих методов:

  • CreateDirectory(path): создает каталог по указанному пути path
  • Delete(path): удаляет каталог по указанному пути path
  • Exists(path): определяет, существует ли каталог по указанному пути path. Если существует, возвращается true, если не существует, то false
  • GetCurrentDirectory(): получает путь к текущей папке
  • GetDirectories(path): получает список подкаталогов в каталоге path
GetFiles(path): получает список файлов в каталоге path GetFileSystemEntries(path): получает список подкаталогов и файлов в каталоге path Move(sourceDirName, destDirName): перемещает каталог GetParent(path): получение родительского каталога GetLastWriteTime(path): возвращает время последнего изменения каталога GetLastAccessTime(path): возвращает время последнего обращения к каталогу GetCreationTime(path): возвращает время создания каталога
  • GetFiles(path): получает список файлов в каталоге path
  • GetFileSystemEntries(path): получает список подкаталогов и файлов в каталоге path
  • Move(sourceDirName, destDirName): перемещает каталог
  • GetParent(path): получение родительского каталога
  • GetLastWriteTime(path): возвращает время последнего изменения каталога
  • GetLastAccessTime(path): возвращает время последнего обращения к каталогу
  • GetCreationTime(path): возвращает время создания каталога
Класс DirectoryInfo Данный класс предоставляет функциональность для создания, удаления, перемещения и других операций с каталогами. Во многом он похож на Directory, но не является статическим.

Класс DirectoryInfo

  • Данный класс предоставляет функциональность для создания, удаления, перемещения и других операций с каталогами. Во многом он похож на Directory, но не является статическим.
Для создания объекта класса DirectoryInfo применяется конструктор, который в качестве параметра принимает путь к каталогу: 1  public DirectoryInfo (string path);
  • Для создания объекта класса DirectoryInfo применяется конструктор, который в качестве параметра принимает путь к каталогу: 1 public DirectoryInfo (string path);
Основные методы класса DirectoryInfo: Create(): создает каталог CreateSubdirectory(path): создает подкаталог по указанному пути path Delete(): удаляет каталог GetDirectories(): получает список подкаталогов папки в виде массива DirectoryInfo GetFiles(): получает список файлов в папке в виде массива FileInfo MoveTo(destDirName): перемещает каталог

Основные методы класса DirectoryInfo:

  • Create(): создает каталог
  • CreateSubdirectory(path): создает подкаталог по указанному пути path
  • Delete(): удаляет каталог
  • GetDirectories(): получает список подкаталогов папки в виде массива DirectoryInfo
  • GetFiles(): получает список файлов в папке в виде массива FileInfo
  • MoveTo(destDirName): перемещает каталог
Основные свойства класса DirectoryInfo: CreationTime: представляет время создания каталога LastAccessTime: представляет время последнего доступа к каталогу LastWriteTime: представляет время последнего изменения каталога Exists: определяет, существует ли каталог Parent: получение родительского каталога Root: получение корневого каталога Name: имя каталога FullName: полный путь к каталогу

Основные свойства класса DirectoryInfo:

  • CreationTime: представляет время создания каталога
  • LastAccessTime: представляет время последнего доступа к каталогу
  • LastWriteTime: представляет время последнего изменения каталога
  • Exists: определяет, существует ли каталог
  • Parent: получение родительского каталога
  • Root: получение корневого каталога
  • Name: имя каталога
  • FullName: полный путь к каталогу
Directory или DirectoryInfo Как видно из функционала, оба класса предоставляют похожие возможности. Когда же и что использовать? Если надо совершить одну-две операции с одним каталогом, то проще использовать класс Directory. Если необходимо выполнить последовательность операций с одним и тем же каталогом, то лучше воспользоваться классом DirectoryInfo. Почему? Дело в том, что методы класса Directory выполняют дополнительные проверки безопасности. А для класса DirectoryInfo такие проверки не всегда обязательны.

Directory или DirectoryInfo

  • Как видно из функционала, оба класса предоставляют похожие возможности. Когда же и что использовать? Если надо совершить одну-две операции с одним каталогом, то проще использовать класс Directory. Если необходимо выполнить последовательность операций с одним и тем же каталогом, то лучше воспользоваться классом DirectoryInfo. Почему? Дело в том, что методы класса Directory выполняют дополнительные проверки безопасности. А для класса DirectoryInfo такие проверки не всегда обязательны.
Посмотрим на примерах применение этих классов Получение списка файлов и подкаталогов Обратите внимание на использование слешей в именах файлов. Либо мы используем двойной слеш:

Посмотрим на примерах применение этих классов

  • Получение списка файлов и подкаталогов

Обратите внимание на использование слешей в именах файлов. Либо мы используем двойной слеш: "C:\\", либо одинарный, но тогда перед всем путем ставим знак @: @"C:\Program Files"

Аналогичный пример с DirectoryInfo:

Аналогичный пример с DirectoryInfo:

Фильтрация папок и файлов Методы получения папок и файлов позволяют выполнять фильтрацию. В качестве фильтра в эти методы передается шаблон, который может содержать два плейсхолдера: * или символ-звездочка (соответствует любому количеству символов) и ? или вопросительный знак (соответствует одному символу)

Фильтрация папок и файлов

  • Методы получения папок и файлов позволяют выполнять фильтрацию. В качестве фильтра в эти методы передается шаблон, который может содержать два плейсхолдера: * или символ-звездочка (соответствует любому количеству символов) и ? или вопросительный знак (соответствует одному символу)
Например, найдем все папки, которые начинаются на
  • Например, найдем все папки, которые начинаются на "books":
Или получим все файлы с расширением
  • Или получим все файлы с расширением ".exe":
Создание каталога Класс DirectoryInfo Вначале проверяем, а нету ли такой директории, так как если она существует, то ее создать будет нельзя, и приложение выбросит ошибку. В итоге у нас получится следующий путь:

Создание каталога

  • Класс DirectoryInfo

Вначале проверяем, а нету ли такой директории, так как если она существует, то ее создать будет нельзя, и приложение выбросит ошибку. В итоге у нас получится следующий путь: "C:\SomeDir\program\avalon"

Аналогичный пример с классом Directory:

Аналогичный пример с классом Directory:

Получение информации о каталоге

Получение информации о каталоге

Удаление каталога Если мы просто применим метод Delete к непустой папке, в которой есть какие-нибудь файлы или подкаталоги, то приложение нам выбросит ошибку. Поэтому нам надо передать в метод Delete дополнительный параметр булевого типа, который укажет, что папку надо удалять со всем содержимым. Кроме того, перед удалением следует проверить наличие удаляемой папки, иначе приложение выбросит исключение:

Удаление каталога

  • Если мы просто применим метод Delete к непустой папке, в которой есть какие-нибудь файлы или подкаталоги, то приложение нам выбросит ошибку. Поэтому нам надо передать в метод Delete дополнительный параметр булевого типа, который укажет, что папку надо удалять со всем содержимым. Кроме того, перед удалением следует проверить наличие удаляемой папки, иначе приложение выбросит исключение:
Или так:

Или так:

Перемещение каталога При перемещении надо учитывать, что новый каталог, в который мы хотим перемесить все содержимое старого каталога, не должен существовать. Перемещение каталога в рамках одной папки (как в примере выше) фактически аналогично переименованию папки

Перемещение каталога

  • При перемещении надо учитывать, что новый каталог, в который мы хотим перемесить все содержимое старого каталога, не должен существовать.

Перемещение каталога в рамках одной папки (как в примере выше) фактически аналогично переименованию папки

Работа с файлами. Классы File и FileInfo Подобно паре Directory/DirectoryInfo для работы с файлами предназначена пара классов File и FileInfo. С их помощью мы можем создавать, удалять, перемещать файлы, получать их свойства и многое другое.

Работа с файлами. Классы File и FileInfo

  • Подобно паре Directory/DirectoryInfo для работы с файлами предназначена пара классов File и FileInfo. С их помощью мы можем создавать, удалять, перемещать файлы, получать их свойства и многое другое.
Некоторые полезные методы и свойства класса FileInfo: CopyTo(path): копирует файл в новое место по указанному пути path Create(): создает файл Delete(): удаляет файл MoveTo(destFileName): перемещает файл в новое место Свойство Directory: получает родительский каталог в виде объекта DirectoryInfo

Некоторые полезные методы и свойства класса FileInfo:

  • CopyTo(path): копирует файл в новое место по указанному пути path
  • Create(): создает файл
  • Delete(): удаляет файл
  • MoveTo(destFileName): перемещает файл в новое место
  • Свойство Directory: получает родительский каталог в виде объекта DirectoryInfo
Свойство DirectoryName: получает полный путь к родительскому каталогу Свойство Exists: указывает, существует ли файл Свойство Length: получает размер файла Свойство Extension: получает расширение файла Свойство Name: получает имя файла Свойство FullName: получает полное имя файла
  • Свойство DirectoryName: получает полный путь к родительскому каталогу
  • Свойство Exists: указывает, существует ли файл
  • Свойство Length: получает размер файла
  • Свойство Extension: получает расширение файла
  • Свойство Name: получает имя файла
  • Свойство FullName: получает полное имя файла
Класс File реализует похожую функциональность с помощью статических методов:
  • Класс File реализует похожую функциональность с помощью статических методов:
Copy(): копирует файл в новое место Create(): создает файл Delete(): удаляет файл Move: перемещает файл в новое место Exists(file): определяет, существует ли файл
  • Copy(): копирует файл в новое место
  • Create(): создает файл
  • Delete(): удаляет файл
  • Move: перемещает файл в новое место
  • Exists(file): определяет, существует ли файл
Получение информации о файле

Получение информации о файле

Удаление файла

Удаление файла

Перемещение файла

Перемещение файла

Копирование файла

Копирование файла

Метод CopyTo класса FileInfo принимает два параметра: путь, по которому файл будет копироваться, и булевое значение, которое указывает, надо ли при копировании перезаписывать файл (если true, как в случае выше, файл при копировании перезаписывается). Если же в качестве последнего параметра передать значение false, то если такой файл уже существует, приложение выдаст ошибку.
  • Метод CopyTo класса FileInfo принимает два параметра: путь, по которому файл будет копироваться, и булевое значение, которое указывает, надо ли при копировании перезаписывать файл (если true, как в случае выше, файл при копировании перезаписывается). Если же в качестве последнего параметра передать значение false, то если такой файл уже существует, приложение выдаст ошибку.
Метод Copy класса File принимает три параметра: путь к исходному файлу, путь, по которому файл будет копироваться, и булевое значение, указывающее, будет ли файл перезаписываться.
  • Метод Copy класса File принимает три параметра: путь к исходному файлу, путь, по которому файл будет копироваться, и булевое значение, указывающее, будет ли файл перезаписываться.
FileStream. Чтение и запись файла Класс FileStream представляет возможности по считыванию из файла и записи в файл. Он позволяет работать как с текстовыми файлами, так и с бинарными.

FileStream. Чтение и запись файла

  • Класс FileStream представляет возможности по считыванию из файла и записи в файл. Он позволяет работать как с текстовыми файлами, так и с бинарными.
Создание FileStream Для создания объекта FileStream можно использовать как конструкторы этого класса, так и статические методы класса File. Конструктор FileStream имеет множество перегруженных версий, из которых отмечу лишь одну, самую простую и используемую:

Создание FileStream

  • Для создания объекта FileStream можно использовать как конструкторы этого класса, так и статические методы класса File. Конструктор FileStream имеет множество перегруженных версий, из которых отмечу лишь одну, самую простую и используемую:
Здесь в конструктор передается два параметра: путь к файлу и перечисление FileMode. Данное перечисление указывает на режим доступа к файлу и может принимать следующие значения:  Append: если файл существует, то текст добавляется в конец файл. Если файла нет, то он создается. Файл открывается только для записи. Create: создается новый файл. Если такой файл уже существует, то он перезаписывается CreateNew: создается новый файл. Если такой файл уже существует, то он приложение выбрасывает ошибку Open: открывает файл. Если файл не существует, выбрасывается исключение OpenOrCreate: если файл существует, он открывается, если нет - создается новый Truncate: если файл существует, то он перезаписывается. Файл открывается только для записи.

Здесь в конструктор передается два параметра: путь к файлу и перечисление FileMode. Данное перечисление указывает на режим доступа к файлу и может принимать следующие значения:

  • Append: если файл существует, то текст добавляется в конец файл. Если файла нет, то он создается. Файл открывается только для записи.
  • Create: создается новый файл. Если такой файл уже существует, то он перезаписывается
  • CreateNew: создается новый файл. Если такой файл уже существует, то он приложение выбрасывает ошибку
  • Open: открывает файл. Если файл не существует, выбрасывается исключение
  • OpenOrCreate: если файл существует, он открывается, если нет - создается новый
  • Truncate: если файл существует, то он перезаписывается. Файл открывается только для записи.
Другой способ создания объекта FileStream представляют статические методы класса File:
  • Другой способ создания объекта FileStream представляют статические методы класса File:
Первый метод открывает файл с учетом объекта FileMode и возвращает файловой поток FileStream. У этого метода также есть несколько перегруженных версий. Второй метод открывает поток для чтения, а третий открывает поток для записи.
  • Первый метод открывает файл с учетом объекта FileMode и возвращает файловой поток FileStream. У этого метода также есть несколько перегруженных версий. Второй метод открывает поток для чтения, а третий открывает поток для записи.
Свойства и методы FileStream Рассмотрим наиболее важные его свойства и методы класса FileStream: Свойство Length: возвращает длину потока в байтах Свойство Position: возвращает текущую позицию в потоке void CopyTo(Stream destination): копирует данные из текущего потока в поток destination Task CopyToAsync(Stream destination): асинхронная версия метода CopyToAsync

Свойства и методы FileStream

Рассмотрим наиболее важные его свойства и методы класса FileStream:

  • Свойство Length: возвращает длину потока в байтах
  • Свойство Position: возвращает текущую позицию в потоке
  • void CopyTo(Stream destination): копирует данные из текущего потока в поток destination
  • Task CopyToAsync(Stream destination): асинхронная версия метода CopyToAsync
int Read(byte[] array, int offset, int count): считывает данные из файла в массив байтов и возвращает количество успешно считанных байтов. Принимает три параметра: array - массив байтов, куда будут помещены считываемые из файла данные offset представляет смещение в байтах в массиве array, в который считанные байты будут помещены count - максимальное число байтов, предназначенных для чтения. Если в файле находится меньшее количество байтов, то все они будут считаны. Task ReadAsync(byte[] array, int offset, int count): асинхронная версия метода Read

int Read(byte[] array, int offset, int count): считывает данные из файла в массив байтов и возвращает количество успешно считанных байтов. Принимает три параметра:

  • array - массив байтов, куда будут помещены считываемые из файла данные
  • offset представляет смещение в байтах в массиве array, в который считанные байты будут помещены
  • count - максимальное число байтов, предназначенных для чтения. Если в файле находится меньшее количество байтов, то все они будут считаны.
  • Task ReadAsync(byte[] array, int offset, int count): асинхронная версия метода Read
long Seek(long offset, SeekOrigin origin): устанавливает позицию в потоке со смещением на количество байт, указанных в параметре offset.
  • long Seek(long offset, SeekOrigin origin): устанавливает позицию в потоке со смещением на количество байт, указанных в параметре offset.
void Write(byte[] array, int offset, int count): записывает в файл данные из массива байтов. Принимает три параметра: array - массив байтов, откуда данные будут записываться в файл offset - смещение в байтах в массиве array, откуда начинается запись байтов в поток count - максимальное число байтов, предназначенных для записи ValueTask WriteAsync(byte[] array, int offset, int count): асинхронная версия метода Write

void Write(byte[] array, int offset, int count): записывает в файл данные из массива байтов. Принимает три параметра:

  • array - массив байтов, откуда данные будут записываться в файл
  • offset - смещение в байтах в массиве array, откуда начинается запись байтов в поток
  • count - максимальное число байтов, предназначенных для записи
  • ValueTask WriteAsync(byte[] array, int offset, int count): асинхронная версия метода Write
Чтение и запись файлов FileStream представляет доступ к файлам на уровне байтов, поэтому, например, если вам надо считать или записать одну или несколько строк в текстовый файл, то массив байтов надо преобразовать в строки, используя специальные методы. Поэтому для работы с текстовыми файлами применяются другие классы.

Чтение и запись файлов

  • FileStream представляет доступ к файлам на уровне байтов, поэтому, например, если вам надо считать или записать одну или несколько строк в текстовый файл, то массив байтов надо преобразовать в строки, используя специальные методы. Поэтому для работы с текстовыми файлами применяются другие классы.
В то же время при работе с различными бинарными файлами, имеющими определенную структуру, FileStream может быть очень даже полезен для извлечения определенных порций информации и ее обработки.
  • В то же время при работе с различными бинарными файлами, имеющими определенную структуру, FileStream может быть очень даже полезен для извлечения определенных порций информации и ее обработки.
Посмотрим на примере считывания-записи в текстовый файл:

Посмотрим на примере считывания-записи в текстовый файл:

Разберем этот пример. Вначале создается папка для файла. Кроме того, на уровне операционной системы могут быть установлены ограничения на запись в определенных каталогах, и при попытке создания и записи файла в подобных каталогах мы получим ошибку.
  • Разберем этот пример. Вначале создается папка для файла. Кроме того, на уровне операционной системы могут быть установлены ограничения на запись в определенных каталогах, и при попытке создания и записи файла в подобных каталогах мы получим ошибку.
И при чтении, и при записи используется оператор using. Не надо путать данный оператор с директивой using, которая подключает пространства имен в начале файла кода. Оператор using позволяет создавать объект в блоке кода, по завершению которого вызывается метод Dispose у этого объекта, и, таким образом, объект уничтожается. В данном случае в качестве такого объекта служит переменная fstream.
  • И при чтении, и при записи используется оператор using. Не надо путать данный оператор с директивой using, которая подключает пространства имен в начале файла кода. Оператор using позволяет создавать объект в блоке кода, по завершению которого вызывается метод Dispose у этого объекта, и, таким образом, объект уничтожается. В данном случае в качестве такого объекта служит переменная fstream.
И при записи, и при чтении применяется объект кодировки Encoding.Default из пространства имен System.Text. В данном случае мы используем два его метода: GetBytes для получения массива байтов из строки и GetString для получения строки из массива байтов.
  • И при записи, и при чтении применяется объект кодировки Encoding.Default из пространства имен System.Text. В данном случае мы используем два его метода: GetBytes для получения массива байтов из строки и GetString для получения строки из массива байтов.
В итоге введенная нами строка записывается в файл note.txt. По сути это бинарный файл (не текстовый), хотя если мы в него запишем только строку, то сможем посмотреть в удобочитаемом виде этот файл, открыв его в текстовом редакторе. Однако если мы в него запишем случайные байты, например:
  • В итоге введенная нами строка записывается в файл note.txt. По сути это бинарный файл (не текстовый), хотя если мы в него запишем только строку, то сможем посмотреть в удобочитаемом виде этот файл, открыв его в текстовом редакторе. Однако если мы в него запишем случайные байты, например:
То у нас могут возникнуть проблемы с его пониманием. Поэтому для работы непосредственно с текстовыми файлами предназначены отдельные классы - StreamReader и StreamWriter.
  • То у нас могут возникнуть проблемы с его пониманием. Поэтому для работы непосредственно с текстовыми файлами предназначены отдельные классы - StreamReader и StreamWriter.
Хотя в данном простеньком консольном приложении, но в реальных приложениях рекомендуется использовать асинхронные версии методов FileStream, поскольку операции с файлами могут занимать продолжительное время и являются узким местом в работе программы. Например, изменим выше приведенную программу, применив асинхронные методы:
  • Хотя в данном простеньком консольном приложении, но в реальных приложениях рекомендуется использовать асинхронные версии методов FileStream, поскольку операции с файлами могут занимать продолжительное время и являются узким местом в работе программы. Например, изменим выше приведенную программу, применив асинхронные методы:
Произвольный доступ к файлам Нередко бинарные файлы представляют определенную структуру. И, зная эту структуру, мы можем взять из файла нужную порцию информации или наоборот записать в определенном месте файла определенный набор байтов. Например, в wav-файлах непосредственно звуковые данные начинаются с 44 байта, а до 44 байта идут различные метаданные - количество каналов аудио, частота дискретизации и т.д.

Произвольный доступ к файлам

  • Нередко бинарные файлы представляют определенную структуру. И, зная эту структуру, мы можем взять из файла нужную порцию информации или наоборот записать в определенном месте файла определенный набор байтов. Например, в wav-файлах непосредственно звуковые данные начинаются с 44 байта, а до 44 байта идут различные метаданные - количество каналов аудио, частота дискретизации и т.д.
С помощью метода Seek() мы можем управлять положением курсора потока, начиная с которого производится считывание или запись в файл. Этот метод принимает два параметра: offset (смещение) и позиция в файле. Позиция в файле описывается тремя значениями: SeekOrigin.Begin: начало файла SeekOrigin.End: конец файла SeekOrigin.Current: текущая позиция в файле

С помощью метода Seek() мы можем управлять положением курсора потока, начиная с которого производится считывание или запись в файл. Этот метод принимает два параметра: offset (смещение) и позиция в файле. Позиция в файле описывается тремя значениями:

  • SeekOrigin.Begin: начало файла
  • SeekOrigin.End: конец файла
  • SeekOrigin.Current: текущая позиция в файле
Курсор потока, с которого начинается чтение или запись, смещается вперед на значение offset относительно позиции, указанной в качестве второго параметра. Смещение может быть отрицательным, тогда курсор сдвигается назад, если положительное - то вперед.
  • Курсор потока, с которого начинается чтение или запись, смещается вперед на значение offset относительно позиции, указанной в качестве второго параметра. Смещение может быть отрицательным, тогда курсор сдвигается назад, если положительное - то вперед.
Рассмотрим на примере:

Рассмотрим на примере:

Консольный вывод:

Консольный вывод:

Вызов fstream.Seek(-5, SeekOrigin.End) перемещает курсор потока в конец файлов назад на пять символов: То есть после записи в новый файл строки
  • Вызов fstream.Seek(-5, SeekOrigin.End) перемещает курсор потока в конец файлов назад на пять символов:

То есть после записи в новый файл строки "hello world" курсор будет стоять на позиции символа "w". После этого считываем четыре байта начиная с символа "w". В данной кодировке 1 символ будет представлять 1 байт. Поэтому чтение 4 байтов будет эквивалентно чтению четырех сиволов: "worl". Затем опять же перемещаемся в конец файла, не доходя до конца пять символов (то есть опять же с позиции символа "w"), и осуществляем запись строки "house". Таким образом, строка "house" заменяет строку "world".

Закрытие потока В примерах выше для закрытия потока применяется конструкция using. После того как все операторы и выражения в блоке using отработают, объект FileStream уничтожается. Однако мы можем выбрать и другой способ:

Закрытие потока

  • В примерах выше для закрытия потока применяется конструкция using. После того как все операторы и выражения в блоке using отработают, объект FileStream уничтожается. Однако мы можем выбрать и другой способ:
Если мы не используем конструкцию using, то нам надо явным образом вызвать метод Close(): fstream.Close()
  • Если мы не используем конструкцию using, то нам надо явным образом вызвать метод Close(): fstream.Close()
Чтение и запись текстовых файлов. StreamReader и StreamWriter Класс FileStream не очень удобно применять для работы с текстовыми файлами. К тому же для этого в пространстве System.IO определены специальные классы: StreamReader и StreamWriter.

Чтение и запись текстовых файлов. StreamReader и StreamWriter

  • Класс FileStream не очень удобно применять для работы с текстовыми файлами. К тому же для этого в пространстве System.IO определены специальные классы: StreamReader и StreamWriter.
Запись в файл и StreamWriter Для записи в текстовый файл используется класс StreamWriter. Некоторые из его конструкторов, которые могут применяться для создания объекта StreamWriter: StreamWriter(string path): через параметр path передается путь к файлу, который будет связан с потоком StreamWriter(string path, bool append): параметр append указывает, надо ли добавлять в конец файла данные или же перезаписывать файл. Если равно true, то новые данные добавляются в конец файла. Если равно false, то файл перезаписываетсяя заново StreamWriter(string path, bool append, System.Text.Encoding encoding): параметр encoding указывает на кодировку, которая будет применяться при записи

Запись в файл и StreamWriter

Для записи в текстовый файл используется класс StreamWriter. Некоторые из его конструкторов, которые могут применяться для создания объекта StreamWriter:

  • StreamWriter(string path): через параметр path передается путь к файлу, который будет связан с потоком
  • StreamWriter(string path, bool append): параметр append указывает, надо ли добавлять в конец файла данные или же перезаписывать файл. Если равно true, то новые данные добавляются в конец файла. Если равно false, то файл перезаписываетсяя заново
  • StreamWriter(string path, bool append, System.Text.Encoding encoding): параметр encoding указывает на кодировку, которая будет применяться при записи
Свою функциональность StreamWriter реализует через следующие методы: int Close(): закрывает записываемый файл и освобождает все ресурсы void Flush(): записывает в файл оставшиеся в буфере данные и очищает буфер. Task FlushAsync(): асинхронная версия метода Flush void Write(string value): записывает в файл данные простейших типов, как int, double, char, string и т.д. Соответственно имеет ряд перегруженных версий для записи данных элементарных типов, например, Write(char value), Write(int value), Write(double value) и т.д. Task WriteAsync(string value): асинхронная версия метода Write void WriteLine(string value): также записывает данные, только после записи добавляет в файл символ окончания строки Task WriteLineAsync(string value): асинхронная версия метода WriteLine

Свою функциональность StreamWriter реализует через следующие методы:

  • int Close(): закрывает записываемый файл и освобождает все ресурсы
  • void Flush(): записывает в файл оставшиеся в буфере данные и очищает буфер.
  • Task FlushAsync(): асинхронная версия метода Flush
  • void Write(string value): записывает в файл данные простейших типов, как int, double, char, string и т.д. Соответственно имеет ряд перегруженных версий для записи данных элементарных типов, например, Write(char value), Write(int value), Write(double value) и т.д.
  • Task WriteAsync(string value): асинхронная версия метода Write
  • void WriteLine(string value): также записывает данные, только после записи добавляет в файл символ окончания строки
  • Task WriteLineAsync(string value): асинхронная версия метода WriteLine
Рассмотрим запись в файл на примере:

Рассмотрим запись в файл на примере:

В данном случае два раза создаем объект StreamWriter. В первом случае если файл существует, то он будет перезаписан. Если не существует, он будет создан. И в нее будет записан текст из переменной text. Во втором случае файл открывается для дозаписи, и будут записаны атомарные данные - строка и число. В обоих случаях будет использоваться кодировка по умолчанию.
  • В данном случае два раза создаем объект StreamWriter. В первом случае если файл существует, то он будет перезаписан. Если не существует, он будет создан. И в нее будет записан текст из переменной text. Во втором случае файл открывается для дозаписи, и будут записаны атомарные данные - строка и число. В обоих случаях будет использоваться кодировка по умолчанию.
По завершении программы в папке C://SomeDir мы сможем найти файл hta.txt, который будет иметь следующие строки:
  • По завершении программы в папке C://SomeDir мы сможем найти файл hta.txt, который будет иметь следующие строки:
Поскольку операции с файлами могут занимать продолжительное время, то в общем случае рекомендуется использовать асинхронную запись. Используем асинхронные версии методов:
  • Поскольку операции с файлами могут занимать продолжительное время, то в общем случае рекомендуется использовать асинхронную запись. Используем асинхронные версии методов:
Обратите внимание, что асинхронные версии есть не для всех перегрузок метода Write.

Обратите внимание, что асинхронные версии есть не для всех перегрузок метода Write.

Чтение из файла и StreamReader Класс StreamReader позволяет нам легко считывать весь текст или отдельные строки из текстового файла.

Чтение из файла и StreamReader

  • Класс StreamReader позволяет нам легко считывать весь текст или отдельные строки из текстового файла.
Некоторые из конструкторов класса StreamReader: StreamReader(string path): через параметр path передается путь к считываемому файлу StreamReader(string path, System.Text.Encoding encoding): параметр encoding задает кодировку для чтения файла

Некоторые из конструкторов класса StreamReader:

  • StreamReader(string path): через параметр path передается путь к считываемому файлу
  • StreamReader(string path, System.Text.Encoding encoding): параметр encoding задает кодировку для чтения файла
Среди методов StreamReader можно выделить следующие: void Close(): закрывает считываемый файл и освобождает все ресурсы int Peek(): возвращает следующий доступный символ, если символов больше нет, то возвращает -1 int Read(): считывает и возвращает следующий символ в численном представлении. Имеет перегруженную версию: Read(char[] array, int index, int count), где array - массив, куда считываются символы, index - индекс в массиве array, начиная с которого записываются считываемые символы, и count - максимальное количество считываемых символов

Среди методов StreamReader можно выделить следующие:

  • void Close(): закрывает считываемый файл и освобождает все ресурсы
  • int Peek(): возвращает следующий доступный символ, если символов больше нет, то возвращает -1
  • int Read(): считывает и возвращает следующий символ в численном представлении. Имеет перегруженную версию: Read(char[] array, int index, int count), где array - массив, куда считываются символы, index - индекс в массиве array, начиная с которого записываются считываемые символы, и count - максимальное количество считываемых символов
Task ReadAsync(): асинхронная версия метода Read string ReadLine(): считывает одну строку в файле string ReadLineAsync(): асинхронная версия метода ReadLine string ReadToEnd(): считывает весь текст из файла string ReadToEndAsync(): асинхронная версия метода ReadToEnd
  • Task ReadAsync(): асинхронная версия метода Read
  • string ReadLine(): считывает одну строку в файле
  • string ReadLineAsync(): асинхронная версия метода ReadLine
  • string ReadToEnd(): считывает весь текст из файла
  • string ReadToEndAsync(): асинхронная версия метода ReadToEnd
Сначала считаем текст полностью из ранее записанного файла:

Сначала считаем текст полностью из ранее записанного файла:

Считаем текст из файла построчно:

Считаем текст из файла построчно:

В данном случае считываем построчно через цикл while: while ((line = sr.ReadLine()) != null) - сначала присваиваем переменной line результат функции sr.ReadLine(), а затем проверяем, не равна ли она null. Когда объект sr дойдет до конца файла и больше строк не останется, то метод sr.ReadLine() будет возвращать null.
  • В данном случае считываем построчно через цикл while: while ((line = sr.ReadLine()) != null) - сначала присваиваем переменной line результат функции sr.ReadLine(), а затем проверяем, не равна ли она null. Когда объект sr дойдет до конца файла и больше строк не останется, то метод sr.ReadLine() будет возвращать null.