file-io rust

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 y BufWriter 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