Rust и файлы: от новичка до мастера работы с файловой системой

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Почему работа с файлами в Rust — это не боль, а удовольствие?

Если вы привыкли к Python, где open() решает почти всё, Rust может показаться строгим преподавателем. Но за этой строгостью скрывается невероятная мощь. Rust не позволит вам случайно оставить открытый файл, прочитать байты как строку или забыть проверить, существует ли директория. В этой статье мы разберем работу с файлами и файловой системой в Rust — от простых операций до продвинутых техник. Вы узнаете, как читать, писать, создавать и удалять файлы, а также как эффективно управлять путями.

Готовы? Поехали!

Основы: открываем, читаем, закрываем

В Rust нет встроенной функции open(), как в Python. Вместо этого мы используем мощный модуль std::fs. Давайте начнем с самого простого — чтения файла целиком.

Чтение всего файла в строку

Самый простой способ прочитать файл — использовать std::fs::read_to_string. Это аналог file.read() в Python, но с гарантией безопасности.

use std::fs;

fn main() {
    let content = fs::read_to_string("hello.txt")
        .expect("Не удалось прочитать файл");
    println!("Содержимое файла:\n{}", content);
}

Обратите внимание на .expect(). В Rust нет исключений — есть Result. Если файла не существует, программа "упадет" с понятным сообщением. Для production-кода лучше использовать match или unwrap_or_else, но для обучения expect идеален.

Запись в файл

Запись также интуитивна:

use std::fs;

fn main() {
    let data = "Hello, Rust!\nЭто тестовая запись.";
    fs::write("output.txt", data)
        .expect("Не удалось записать файл");
    println!("Файл успешно записан!");
}

Метод fs::write создает файл, если его нет, и перезаписывает содержимое, если файл существует. Для добавления данных в конец файла используйте OpenOptions.

Работа с путями: Path и PathBuf

В Rust есть два основных типа для работы с путями: Path (заимствованный, неизменяемый) и PathBuf (собственный, изменяемый). Понимание разницы между ними — ключ к эффективной работе с файловой системой.

Создание и манипуляции с путями

use std::path::{Path, PathBuf};

fn main() {
    // Создаем путь
    let path = Path::new("data/subdir/file.txt");
    
    // Получаем компоненты пути
    println!("Родительская директория: {:?}", path.parent());
    println!("Имя файла: {:?}", path.file_name());
    println!("Расширение: {:?}", path.extension());
    
    // Собираем новый путь
    let mut new_path = PathBuf::from("backup");
    new_path.push("data");
    new_path.push("file.txt");
    println!("Новый путь: {}", new_path.display());
}

Метод .display() обязателен, если вы хотите вывести путь в терминал. Rust не позволяет просто вставить путь в строку — это защита от проблем с кодировками.

Чтение и запись: продвинутый уровень

Когда вам нужно больше контроля, используйте File и BufReader/BufWriter.

Чтение файла построчно

Для больших файлов читать всё в память неэффективно. Используйте буферизованное чтение:

use std::fs::File;
use std::io::{BufRead, BufReader};

fn main() {
    let file = File::open("large_file.txt")
        .expect("Файл не найден");
    let reader = BufReader::new(file);
    
    for (index, line) in reader.lines().enumerate() {
        let line = line.expect("Ошибка чтения строки");
        println!("Строка {}: {}", index + 1, line);
    }
}

Этот подход позволяет обрабатывать файлы любого размера, не загружая их в оперативную память целиком.

Добавление данных в конец файла

Используйте OpenOptions для тонкой настройки:

use std::fs::OpenOptions;
use std::io::Write;

fn main() {
    let mut file = OpenOptions::new()
        .append(true)  // Добавляем, а не перезаписываем
        .create(true)  // Создаем файл, если его нет
        .open("log.txt")
        .expect("Не удалось открыть файл");
    
    writeln!(file, "Новая запись в лог: {}", chrono::Local::now())
        .expect("Ошибка записи");
}

Обратите внимание: мы используем макрос writeln!, который автоматически добавляет новую строку.

Работа с директориями и файловой системой

Rust предоставляет удобные функции для управления файлами и папками.

Создание и удаление директорий

use std::fs;

fn main() {
    // Создаем директорию (и все родительские, если нужно)
    fs::create_dir_all("data/projects/rust")
        .expect("Не удалось создать директорию");
    
    // Удаляем пустую директорию
    fs::remove_dir("data/projects/python")
        .expect("Директория не пуста или не существует");
    
    // Удаляем директорию со всем содержимым (осторожно!)
    fs::remove_dir_all("temp")
        .expect("Не удалось удалить директорию");
}

Функция remove_dir_all работает как rm -rf — будьте внимательны!

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

use std::fs;

fn main() {
    // Копирование
    fs::copy("source.txt", "backup/source_copy.txt")
        .expect("Ошибка копирования");
    
    // Перемещение/переименование
    fs::rename("old_name.txt", "new_name.txt")
        .expect("Ошибка перемещения");
}

Проверка существования и метаданные

use std::fs;
use std::path::Path;

fn main() {
    let path = Path::new("data.txt");
    
    // Проверка существования
    if path.exists() {
        println!("Файл существует");
    }
    
    // Получение метаданных
    if let Ok(metadata) = fs::metadata(path) {
        println!("Размер: {} байт", metadata.len());
        println!("Тип файла: {:?}", metadata.file_type());
        println!("Последняя модификация: {:?}", metadata.modified());
    }
}

Продвинутые техники: рекурсивный обход и поиск

Иногда нужно обработать все файлы в директории рекурсивно. Для этого можно использовать std::fs::read_dir в комбинации с рекурсией.

Рекурсивный обход директорий

use std::fs;
use std::path::Path;

fn visit_dirs(dir: &Path) {
    if dir.is_dir() {
        for entry in fs::read_dir(dir).expect("Ошибка чтения директории")                

Блоги

Рекомендаций по книгам