Ответ 1
Ни одна из функций, которые я здесь показываю, сама по себе не паникует, но я использую expect
, потому что я не знаю, какая обработка ошибок лучше всего подойдет для вашего приложения. Прочитайте главу "Язык программирования Rust" об обработке ошибок, чтобы понять, как правильно обрабатывать ошибки в вашей собственной программе.
Ржавчина 1.26 и выше
Если вы не хотите заботиться о базовых деталях, есть однострочные функции для чтения и записи.
Прочитать файл в String
use std::fs;
fn main() {
let data = fs::read_to_string("/etc/hosts").expect("Unable to read file");
println!("{}", data);
}
Читать файл как Vec<u8>
use std::fs;
fn main() {
let data = fs::read("/etc/hosts").expect("Unable to read file");
println!("{}", data.len());
}
Написать файл
use std::fs;
fn main() {
let data = "Some data!";
fs::write("/tmp/foo", data).expect("Unable to write file");
}
Rust 1.0 и выше
Эти формы немного более многословны, чем однострочные функции, которые выделяют для вас String
или Vec
, но они более мощные, так как вы можете повторно использовать выделенные данные или добавлять к существующему объекту.
Чтение данных
Чтение файла требует двух основных частей: File
и Read
.
Прочитать файл в String
use std::fs::File;
use std::io::Read;
fn main() {
let mut data = String::new();
let mut f = File::open("/etc/hosts").expect("Unable to open file");
f.read_to_string(&mut data).expect("Unable to read string");
println!("{}", data);
}
Читать файл как Vec<u8>
use std::fs::File;
use std::io::Read;
fn main() {
let mut data = Vec::new();
let mut f = File::open("/etc/hosts").expect("Unable to open file");
f.read_to_end(&mut data).expect("Unable to read data");
println!("{}", data.len());
}
Написать файл
Запись файла аналогична, за исключением того, что мы используем черту Write
и мы всегда записываем байты. Вы можете преобразовать String
/&str
в байты с помощью as_bytes
:
use std::fs::File;
use std::io::Write;
fn main() {
let data = "Some data!";
let mut f = File::create("/tmp/foo").expect("Unable to create file");
f.write_all(data.as_bytes()).expect("Unable to write data");
}
Буферизованный ввод/вывод
Я почувствовал, что сообщество немного подтолкнуло использовать
BufReader
иBufWriter
вместо чтения прямо из файла
Буферный считыватель (или записывающее устройство) использует буфер для уменьшения количества запросов ввода-вывода. Например, гораздо эффективнее получить доступ к диску один раз, чтобы прочитать 256 байтов, чем получить доступ к диску 256 раз.
При этом я не верю, что буферизованный читатель/писатель будет полезен при чтении всего файла. read_to_end
, кажется, копирует данные в несколько больших кусках, поэтому передача может уже естественным образом объединиться в меньшее количество запросов ввода/вывода.
Вот пример использования его для чтения:
use std::fs::File;
use std::io::{BufReader, Read};
fn main() {
let mut data = String::new();
let f = File::open("/etc/hosts").expect("Unable to open file");
let mut br = BufReader::new(f);
br.read_to_string(&mut data).expect("Unable to read string");
println!("{}", data);
}
И для записи:
use std::fs::File;
use std::io::{BufWriter, Write};
fn main() {
let data = "Some data!";
let f = File::create("/tmp/foo").expect("Unable to create file");
let mut f = BufWriter::new(f);
f.write_all(data.as_bytes()).expect("Unable to write data");
}
A BufReader
более полезен, если вы хотите читать построчно:
use std::fs::File;
use std::io::{BufRead, BufReader};
fn main() {
let f = File::open("/etc/hosts").expect("Unable to open file");
let f = BufReader::new(f);
for line in f.lines() {
let line = line.expect("Unable to read line");
println!("Line: {}", line);
}
}