vivanov 8939576774 first commit | 11 ماه پیش | |
---|---|---|
.gitignore.txt | 1 سال پیش | |
readme.md | 11 ماه پیش |
Работа с дисками
Класс DriveInfo имеет статический метод GetDrives, который возвращает имена всех логических дисков компьютера. Также он предоставляет ряд полезных свойств:
Получим имена и свойства всех дисков на компьютере:
using System;
using System.IO;
DriveInfo[] drives = DriveInfo.GetDrives();
foreach (DriveInfo drive in drives)
{
Console.WriteLine($"Название: {drive.Name}");
Console.WriteLine($"Тип: {drive.DriveType}");
if (drive.IsReady)
{
Console.WriteLine($"Объем диска: {drive.TotalSize}");
Console.WriteLine($"Свободное пространство: {drive.TotalFreeSpace}");
Console.WriteLine($"Метка: {drive.VolumeLabel}");
}
Console.WriteLine();
}
Вывод:
Название: C:\
Тип: Fixed
Объем диска: 257128853504
Свободное пространство: 50015592448
Метка:
Название: D:\
Тип: Fixed
Объем диска: 644245090304
Свободное пространство: 211880443904
Метка: Новый том
Название: E:\
Тип: Fixed
Объем диска: 1356135919616
Свободное пространство: 1355963248640
Метка: Новый том
Название: F:\
Тип: Fixed
Объем диска: 742383415296
Свободное пространство: 650652270592
Метка: ssd
Работа с каталогами
Класс Directory предоставляет ряд статических методов для управления каталогами. Некоторые из этих методов:
Класс DirectoryInfo
Данный класс предоставляет функциональность для создания, удаления, перемещения и других операций с каталогами. Во многом он похож на Directory. Некоторые из его свойств и методов:
Получение списка файлов и подкаталогов
string dirName = "C:\\";
if (Directory.Exists(dirName))
{
Console.WriteLine("Подкаталоги:");
string[] dirs = Directory.GetDirectories(dirName);
foreach (string s in dirs)
{
Console.WriteLine(s);
}
Console.WriteLine();
Console.WriteLine("Файлы:");
string[] files = Directory.GetFiles(dirName);
foreach (string s in files)
{
Console.WriteLine(s);
}
}
Вывод:
Подкаталоги:
C:\$Recycle.Bin
C:\$WinREAgent
C:\AMD
C:\Documents and Settings
C:\MSI
C:\OneDriveTemp
C:\PerfLogs
C:\Program Files
C:\Program Files (x86)
C:\ProgramData
C:\Recovery
C:\System Volume Information
C:\tenorshare
C:\TwitchLink
C:\Users
C:\Windows
Файлы:
C:\appverifUI.dll
C:\DumpStack.log
C:\DumpStack.log.tmp
C:\hiberfil.sys
C:\pagefile.sys
C:\swapfile.sys
C:\vfcompat.dll
Обратите внимание на использование слешей в именах файлов. Либо мы используем двойной слеш: C:\, либо одинарный, но тогда перед строкой ставим знак @: @"C:\Program Files"
Можно вместо обратных слешей использовать прямые. Windows нормально их воспринимает
Создание каталога
string path = @"C:\SomeDir";
string subpath = @"program\avalon";
DirectoryInfo dirInfo = new DirectoryInfo(path);
if (!dirInfo.Exists)
{
dirInfo.Create();
}
dirInfo.CreateSubdirectory(subpath);
Вначале проверяем, а нет ли такой директории, так как если она существует, то ее создать будет нельзя, и приложение выбросит ошибку. В итоге у нас получится следующий путь: C:\SomeDir\program\avalon
Получение информации о каталоге
string dirName = "C:\\Program Files";
DirectoryInfo dirInfo = new DirectoryInfo(dirName);
Console.WriteLine($"Название каталога: {dirInfo.Name}");
Console.WriteLine($"Полное название каталога: {dirInfo.FullName}");
Console.WriteLine($"Время создания каталога: {dirInfo.CreationTime}");
Console.WriteLine($"Корневой каталог: {dirInfo.Root}");
Удаление каталога
Нам нужно передать в метод Delete
дополнительный параметр булевого типа, который укажет, что папку надо удалять со всем содержимым (иначе не получится):
string dirName = @"C:\SomeFolder";
try
{
DirectoryInfo dirInfo = new DirectoryInfo(dirName);
dirInfo.Delete(true);
Console.WriteLine("Каталог удален");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Либо так:
string dirName = @"C:\SomeFolder";
Directory.Delete(dirName, true);
Перемещение каталога
string oldPath = @"C:\SomeFolder";
string newPath = @"C:\SomeDir";
DirectoryInfo dirInfo = new DirectoryInfo(oldPath);
if (dirInfo.Exists && Directory.Exists(newPath) == false)
{
dirInfo.MoveTo(newPath);
}
При перемещении надо учитывать, что новый каталог, в который мы хотим перемесить все содержимое старого каталога, не должен существовать.
Работа с файлами. Классы File и FileInfo
Подобно паре Directory/DirectoryInfo для работы с файлами предназначена пара классов File и FileInfo. С их помощью мы можем создавать, удалять, перемещать файлы, получать их свойства и многое другое.
Некоторые полезные методы и свойства класса FileInfo
:
CopyTo(path)
копирует файл в новое место по указанному пути pathCreate()
: создает файлDelete()
: удаляет файлMoveTo(destFileName)
: перемещает файл в новое местоDirectory
: получает родительский каталог в виде объекта DirectoryInfoDirectoryName
: получает полный путь к родительскому каталогуExists
: указывает, существует ли файлLength
: получает размер файлаExtension
: получает расширение файлаName
: получает имя файлаFullName
: получает полное имя файлаКласс File реализует похожую функциональность с помощью статических методов:
Copy()
: копирует файл в новое местоCreate()
: создает файлDelete()
: удаляет файлMove
: перемещает файл в новое местоExists(file)
: определяет, существует ли файлПолучение информации о файле
string path = @"C:\apache\hta.txt";
FileInfo fileInf = new FileInfo(path);
if (fileInf.Exists)
{
Console.WriteLine("Имя файла: {0}", fileInf.Name);
Console.WriteLine("Время создания: {0}", fileInf.CreationTime);
Console.WriteLine("Размер: {0}", fileInf.Length);
}
Удаление файла
string path = @"C:\apache\hta.txt";
FileInfo fileInf = new FileInfo(path);
if (fileInf.Exists)
{
fileInf.Delete();
// альтернатива с помощью класса File
// File.Delete(path);
}
Перемещение файла
string path = @"C:\apache\hta.txt";
string newPath = @"C:\SomeDir\hta.txt";
FileInfo fileInf = new FileInfo(path);
if (fileInf.Exists)
{
fileInf.MoveTo(newPath);
// альтернатива с помощью класса File
// File.Move(path, newPath);
}
Копирование файла
string path = @"C:\apache\hta.txt";
string newPath = @"C:\SomeDir\hta.txt";
FileInfo fileInf = new FileInfo(path);
if (fileInf.Exists)
{
fileInf.CopyTo(newPath, true);
// альтернатива с помощью класса File
// File.Copy(path, newPath, true);
}
FileStream. Чтение и запись файла
Класс FileStream представляет возможности по считыванию из файла и записи в файл. Он позволяет работать как с текстовыми файлами, так и с бинарными.
Создание FileStream
FileStream(string filename, FileMode mode)
Здесь в конструктор передается два параметра: путь к файлу и перечисление (enum) FileMode. Данное перечисление указывает на режим доступа к файлу и может принимать следующие значения:
Append
: если файл существует, то текст добавляется в конец файл. Если файла нет, то он создается. Файл открывается только для записи.
Create
: создается новый файл. Если такой файл уже существует, то он перезаписывается
CreateNew
: создается новый файл. Если такой файл уже существует, то он приложение выбрасывает ошибку
Open
: открывает файл. Если файл не существует, выбрасывается исключение
OpenOrCreate
: если файл существует, он открывается, если нет - создается новый
Truncate
: если файл существует, то он перезаписывается. Файл открывается только для записи.
Другой способ создания объекта FileStream представляют статические методы класса File:
FileStream File.Open(string file, FileMode mode);
FileStream File.OpenRead(string file);
FileStream File.OpenWrite(string file);
Свойства и методы 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<int> ReadAsync(byte[] array, int offset, int count)
: асинхронная версия метода Read
long Seek(long offset, SeekOrigin origin)
: устанавливает позицию в потоке со смещением на количество байт, указанных в параметре offset.
void Write(byte[] array, int offset, int count)
: записывает в файл данные из массива байтов. Принимает три параметра:
offset
- смещение в байтах в массиве array, откуда начинается запись байтов в поток
count
- максимальное число байтов, предназначенных для записи
ValueTask WriteAsync(byte[] array, int offset, int count)
: асинхронная версия метода Write
Чтение и запись файлов
FileStream представляет доступ к файлам на уровне байтов, поэтому, например, если вам надо считать или записать одну или несколько строк в текстовый файл, то массив байтов надо преобразовать в строки, используя специальные методы. Поэтому для работы с текстовыми файлами применяются другие классы.
В то же время при работе с различными бинарными файлами, имеющими определенную структуру, FileStream может быть очень даже полезен для извлечения определенных порций информации и ее обработки.
Посмотрим на примере считывания-записи в текстовый файл:
using System;
using System.IO;
namespace HelloApp
{
class Program
{
static void Main(string[] args)
{
// создаем каталог для файла
string path = @"C:\SomeDir2";
DirectoryInfo dirInfo = new DirectoryInfo(path);
if (!dirInfo.Exists)
{
dirInfo.Create();
}
Console.WriteLine("Введите строку для записи в файл:");
string text = Console.ReadLine();
// запись в файл
using (FileStream fstream = new FileStream($"{path}\note.txt", FileMode.OpenOrCreate))
{
// преобразуем строку в байты
byte[] array = System.Text.Encoding.Default.GetBytes(text);
// запись массива байтов в файл
fstream.Write(array, 0, array.Length);
Console.WriteLine("Текст записан в файл");
}
// чтение из файла
using (FileStream fstream = File.OpenRead($"{path}\note.txt"))
{
// преобразуем строку в байты
byte[] array = new byte[fstream.Length];
// считываем данные
fstream.Read(array, 0, array.Length);
// декодируем байты в строку
string textFromFile = System.Text.Encoding.Default.GetString(array);
Console.WriteLine($"Текст из файла: {textFromFile}");
}
Console.ReadLine();
}
}
}
Изменим выше приведенную программу, применив асинхронные методы:
using System;
using System.IO;
using System.Threading.Tasks;
namespace HelloApp
{
class Program
{
static async Task Main(string[] args)
{
// создаем каталог для файла
string path = @"C:\SomeDir3";
DirectoryInfo dirInfo = new DirectoryInfo(path);
if (!dirInfo.Exists)
{
dirInfo.Create();
}
Console.WriteLine("Введите строку для записи в файл:");
string text = Console.ReadLine();
// запись в файл
using (FileStream fstream = new FileStream($"{path}\note.txt", FileMode.OpenOrCreate))
{
byte[] array = System.Text.Encoding.Default.GetBytes(text);
// асинхронная запись массива байтов в файл
await fstream.WriteAsync(array, 0, array.Length);
Console.WriteLine("Текст записан в файл");
}
// чтение из файла
using (FileStream fstream = File.OpenRead($"{path}\note.txt"))
{
byte[] array = new byte[fstream.Length];
// асинхронное чтение файла
await fstream.ReadAsync(array, 0, array.Length);
string textFromFile = System.Text.Encoding.Default.GetString(array);
Console.WriteLine($"Текст из файла: {textFromFile}");
}
Console.ReadLine();
}
}
}
Произвольный доступ к файлам
С помощью метода Seek
мы можем управлять положением курсора потока, начиная с которого производится считывание или запись в файл. Этот метод принимает два параметра: offset (смещение) и позиция в файле. Позиция в файле описывается тремя значениями:
SeekOrigin.Begin
: начало файла
SeekOrigin.End
: конец файла
SeekOrigin.Current
: текущая позиция в файле
Курсор потока, с которого начинается чтение или запись, смещается вперед на значение offset относительно позиции, указанной в качестве второго параметра. Смещение может быть отрицательным, тогда курсор сдвигается назад, если положительное - то вперед.
Рассмотрим на примере:
using System.IO;
using System.Text;
class Program
{
static void Main(string[] args)
{
string text = "hello world";
// запись в файл
using (FileStream fstream = new FileStream(@"D:\note.dat", FileMode.OpenOrCreate))
{
// преобразуем строку в байты
byte[] input = Encoding.Default.GetBytes(text);
// запись массива байтов в файл
fstream.Write(input, 0, input.Length);
Console.WriteLine("Текст записан в файл");
// перемещаем указатель в конец файла, до конца файла- пять байт
fstream.Seek(-5, SeekOrigin.End); // минус 5 символов с конца потока
// считываем четыре символов с текущей позиции
byte[] output = new byte[4];
fstream.Read(output, 0, output.Length);
// декодируем байты в строку
string textFromFile = Encoding.Default.GetString(output);
Console.WriteLine($"Текст из файла: {textFromFile}"); // worl
// заменим в файле слово world на слово house
string replaceText = "house";
fstream.Seek(-5, SeekOrigin.End); // минус 5 символов с конца потока
input = Encoding.Default.GetBytes(replaceText);
fstream.Write(input, 0, input.Length);
// считываем весь файл
// возвращаем указатель в начало файла
fstream.Seek(0, SeekOrigin.Begin);
output = new byte[fstream.Length];
fstream.Read(output, 0, output.Length);
// декодируем байты в строку
textFromFile = Encoding.Default.GetString(output);
Console.WriteLine($"Текст из файла: {textFromFile}"); // hello house
}
Console.Read();
}
}
Вывод:
Текст записан в файл
Текст из файла: worl
Текст из файла: hello house
Закрытие потока
В примерах выше для закрытия потока применяется конструкция using. После того как все операторы и выражения в блоке using отработают, объект FileStream уничтожается. Однако мы можем выбрать и другой способ:
FileStream fstream = null;
try
{
fstream = new FileStream(@"D:\note3.dat", FileMode.OpenOrCreate);
// операции с потоком
}
catch(Exception ex)
{
}
finally
{
if (fstream != null)
fstream.Close();
}
Если мы не используем конструкцию using
, то нам надо явным образом вызвать метод Close: fstream.Close()
Чтение и запись текстовых файлов. 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 реализует через следующие методы:
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
using System;
using System.IO;
namespace HelloApp
{
class Program
{
static void Main(string[] args)
{
string writePath = @"C:\SomeDir\hta.txt";
string text = "Привет мир!\nПока мир...";
try
{
using (StreamWriter sw = new StreamWriter(
writePath, false, System.Text.Encoding.Default))
{
sw.WriteLine(text);
}
using (StreamWriter sw = new StreamWriter(
writePath, true, System.Text.Encoding.Default))
{
sw.WriteLine("Дозапись");
sw.Write(4.5);
}
Console.WriteLine("Запись выполнена");
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
}
}
Вывод:
Привет мир!
Пока мир...
Дозапись
4,5
Используем асинхронные версии методов:
using System;
using System.IO;
using System.Threading.Tasks;
namespace HelloApp
{
class Program
{
static async Task Main(string[] args)
{
string writePath = @"C:\SomeDir\hta2.txt";
string text = "Привет мир!\nПока мир...";
try
{
using (StreamWriter sw = new StreamWriter(
writePath, false, System.Text.Encoding.Default))
{
await sw.WriteLineAsync(text);
}
using (StreamWriter sw = new StreamWriter(
writePath, true, System.Text.Encoding.Default))
{
await sw.WriteLineAsync("Дозапись");
await sw.WriteAsync("4,5");
}
Console.WriteLine("Запись выполнена");
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
}
}
Обратите внимание, что асинхронные версии есть не для всех перегрузок метода Write.
Чтение из файла и StreamReader
Класс StreamReader позволяет нам легко считывать весь текст или отдельные строки из текстового файла.
Некоторые из конструкторов класса 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 - максимальное количество считываемых символов
Task<int> ReadAsync()
: асинхронная версия метода Rea
string ReadLine()
: считывает одну строку в файле
string ReadLineAsync()
: асинхронная версия метода ReadLine
string ReadToEnd()
: считывает весь текст из файла
string ReadToEndAsync()
: асинхронная версия метода ReadToEnd
using System;
using System.IO;
using System.Threading.Tasks;
string path = @"C:\SomeDir\hta.txt";
try
{
using (StreamReader sr = new StreamReader(path))
{
Console.WriteLine(sr.ReadToEnd());
}
// асинхронное чтение
using (StreamReader sr = new StreamReader(path))
{
Console.WriteLine(await sr.ReadToEndAsync());
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
Считаем текст из файла построчно:
string path= @"C:\SomeDir\hta.txt";
using (StreamReader sr = new StreamReader(path, System.Text.Encoding.Default))
{
string line;
while ((line = sr.ReadLine()) != null)
{
Console.WriteLine(line);
}
}
// асинхронное чтение
using (StreamReader sr = new StreamReader(path, System.Text.Encoding.Default))
{
string line;
while ((line = await sr.ReadLineAsync()) != null)
{
Console.WriteLine(line);
}
}