file io - ¿Cuál es la forma de facto de leer y escribir archivos en Rust 1.x?
file-io (1)
Ninguna de las funciones que muestro aquí entra en pánico por sí mismas, pero estoy usando
expect
porque no sé qué tipo de manejo de errores se ajustará mejor a su aplicación.
Vaya a leer el
capítulo del
lenguaje de programación de Rust
sobre manejo de errores
para comprender cómo manejar adecuadamente las fallas en su propio programa.
Óxido 1.26 y en adelante
Si no desea preocuparse por los detalles subyacentes, hay funciones de una línea para leer y escribir.
Leer un archivo a una
String
use std::fs;
fn main() {
let data = fs::read_to_string("/etc/hosts").expect("Unable to read file");
println!("{}", data);
}
Leer un archivo como
Vec<u8>
use std::fs;
fn main() {
let data = fs::read("/etc/hosts").expect("Unable to read file");
println!("{}", data.len());
}
Escribir un archivo
use std::fs;
fn main() {
let data = "Some data!";
fs::write("/tmp/foo", data).expect("Unable to write file");
}
Rust 1.0 y en adelante
Estas formas son un poco más detalladas que las funciones de una línea que asignan un
String
o
Vec
para usted, pero son más poderosas en el sentido de que puede reutilizar los datos asignados o agregarlos a un objeto existente.
Lectura de datos
Leer un archivo requiere dos piezas principales:
File
y
Read
.
Leer un archivo a una
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);
}
Leer un archivo como
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());
}
Escribir un archivo
Escribir un archivo es similar, excepto que usamos el rasgo
Write
y siempre escribimos bytes.
Puede convertir un
String
/
&str
a bytes con
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");
}
E / S almacenadas
Sentí un pequeño empujón de la comunidad para usar
BufReader
yBufWriter
lugar de leer directamente de un archivo
Un lector (o escritor) con búfer utiliza un búfer para reducir la cantidad de solicitudes de E / S. Por ejemplo, es mucho más eficiente acceder al disco una vez para leer 256 bytes en lugar de acceder al disco 256 veces.
Dicho esto, no creo que un lector / escritor protegido sea útil al leer el archivo completo.
read_to_end
parece copiar datos en fragmentos algo grandes, por lo que la transferencia puede estar naturalmente unida en menos solicitudes de E / S.
Aquí hay un ejemplo de cómo usarlo para leer:
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);
}
Y para escribir:
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");
}
Un
BufReader
es más útil cuando quieres leer línea por línea:
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);
}
}
Con Rust siendo relativamente nuevo, he visto demasiadas formas de leer y escribir archivos. Muchos son fragmentos extremadamente desordenados que alguien ideó para su blog, y el 99% de los ejemplos que he encontrado (incluso en Stack Overflow) son de compilaciones inestables que ya no funcionan. Ahora que Rust es estable, ¿qué es un fragmento simple, legible y sin pánico para leer o escribir archivos?
Esto es lo más cerca que he estado de algo que funciona en términos de lectura de un archivo de texto, pero todavía no se está compilando, aunque estoy bastante seguro de haber incluido todo lo que debería tener.
Esto se basa en un fragmento que encontré en Google+ de todos los lugares, y lo único que he cambiado es que el viejo
BufferedReader
ahora es solo
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);
}
}
El compilador se queja:
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() {
|> ^^^^^
Para resumir, lo que estoy buscando es:
- brevedad
- legibilidad
- cubre todos los posibles errores
- no se asusta