Поскольку Rust был сравнительно новым, я видел слишком много способов чтения и записи файлов. Многие из них представляют собой чрезвычайно запутанные фрагменты, которые кто-то придумал для своего блога, и 99% примеров, которые я нашел (даже в Stack Overflow), относятся к нестабильным сборкам, которые больше не работают. Теперь, когда Rust стабилен, что такое простой, читаемый, не вызывающий паники фрагмент кода для чтения или записи файлов?
Это ближе всего к чему-то, что работает с точки зрения чтения текстового файла, но он все еще не компилируется, хотя я вполне уверен, что включил все, что должно было иметь. Это основано на фрагменте, который я нашел в Google+ во всех местах, и единственное, что я изменил, это то, что старый BufferedReader
теперь просто BufReader
:
use std::fs::File;
use std::io::BufReader;
use std::path::Path;
fn main() {
let path = Path::new("./textfile");
let mut file = BufReader::new(File::open(&path));
for line in file.lines() {
println!("{}", line);
}
}
Компилятор жалуется:
error: the trait bound `std::result::Result<std::fs::File, std::io::Error>: std::io::Read` is not satisfied [--explain E0277]
--> src/main.rs:7:20
|>
7 |> let mut file = BufReader::new(File::open(&path));
|> ^^^^^^^^^^^^^^
note: required by `std::io::BufReader::new`
error: no method named `lines` found for type `std::io::BufReader<std::result::Result<std::fs::File, std::io::Error>>` in the current scope
--> src/main.rs:8:22
|>
8 |> for line in file.lines() {
|> ^^^^^
Подводя итог, я ищу:
- краткость
- читабельность
- охватывает все возможные ошибки
- не паникует
std::io::Read
), обратите внимание, что в Rust вы должны явно импортировать трейты, которые вы ожидаете использовать ; таким образом, здесь вам не хватаетuse std::io::Read
(который может бытьuse std::io::{Read,BufReader}
объединением двух использований вместе)Ответы:
Ни одна из функций, которые я здесь показываю, не вызывает паники сама по себе, но я использую,
expect
потому что не знаю, какой тип обработки ошибок лучше всего подходит для вашего приложения. Прочтите главу « Язык программирования Rust », посвященную обработке ошибок, чтобы понять, как правильно обрабатывать сбой в вашей собственной программе.Rust 1.26 и новее
Если вы не хотите заботиться об основных деталях, есть однострочные функции для чтения и записи.
Прочитать файл в
String
Прочитать файл как
Vec<u8>
Написать файл
Rust 1.0 и новее
Эти формы немного более подробны, чем однострочные функции, которые выделяют
String
илиVec
для вас, но более эффективны в том, что вы можете повторно использовать выделенные данные или добавить их к существующему объекту.Чтение данных
Для чтения файла требуются две основные части:
File
иRead
.Прочитать файл в
String
Прочитать файл как
Vec<u8>
Написать файл
Запись файла аналогична, за исключением того, что мы используем
Write
типаж и всегда записываем байты. Вы можете преобразоватьString
/&str
в байты с помощьюas_bytes
:Буферизованный ввод / вывод
Буферизованный считыватель (или писатель) использует буфер для уменьшения количества запросов ввода-вывода. Например, гораздо эффективнее получить доступ к диску один раз, чтобы прочитать 256 байтов, чем обращаться к диску 256 раз.
При этом я не верю, что буферизованный читатель / писатель будет полезен при чтении всего файла.
read_to_end
кажется, что данные копируются в несколько больших фрагментов, поэтому передача уже может быть естественным образом объединена в меньшее количество запросов ввода-вывода.Вот пример использования его для чтения:
И для написания:
A
BufReader
более полезен, если вы хотите читать построчно:источник
b"foobar"
- это литерал для создания ссылки на массив bytes (&[u8; N]
). Таким образом, он неизменен. Нет ничего из того, что нельзя было бы сделать проще.Vec<u8>
для чтения и записи. Это необработанные байты.