Quelle est la manière de facto de lire et d’écrire des fichiers dans Rust 1.x?

Rust étant relativement nouveau, j’ai vu beaucoup trop de façons de lire et d’écrire des fichiers. Beaucoup sont des extraits extrêmement désordonnés que quelqu’un a créés pour leur blog, et 99% des exemples que j’ai trouvés (même sur Stack Overflow) proviennent de versions instables qui ne fonctionnent plus. Maintenant que Rust est stable, qu’est-ce qu’un extrait simple, lisible et sans paniquer pour lire ou écrire des fichiers?

C’est le plus proche de tout ce qui fonctionne en termes de lecture d’un fichier texte, mais cela ne comstack toujours pas, même si je suis presque certain d’avoir inclus tout ce que je devrais avoir. Ceci est basé sur un extrait que j’ai trouvé sur Google+ de tous les endroits, et la seule chose que j’ai changée est que l’ancien BufferedReader est maintenant juste 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); } } 

Le compilateur se plaint:

 error: the trait bound `std::result::Result: 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>` in the current scope --> src/main.rs:8:22 |> 8 |> for line in file.lines() { |> ^^^^^ 

Pour résumer, ce que je recherche, c’est:

  • brièveté
  • lisibilité
  • couvre toutes les erreurs possibles
  • ne panique pas

Aucune des fonctions que je montre ici ne panique par lui-même, mais je m’attends à expect que je sache, car je ne sais pas quel type de traitement des erreurs correspond le mieux à votre application. Allez lire le chapitre du langage de programmation de Rust sur la gestion des erreurs pour comprendre comment gérer correctement les défaillances dans votre propre programme.

rust 1.26 et plus

Si vous ne voulez pas vous soucier des détails sous-jacents, il existe des fonctions à une ligne pour la lecture et l’écriture.

Lire un fichier sur une Ssortingng

 use std::fs; fn main() { let data = fs::read_to_ssortingng("/etc/hosts").expect("Unable to read file"); println!("{}", data); } 

Lire un fichier en tant que fichier Vec

 use std::fs; fn main() { let data = fs::read("/etc/hosts").expect("Unable to read file"); println!("{}", data.len()); } 

Ecrire un fichier

 use std::fs; fn main() { let data = "Some data!"; fs::write("/tmp/foo", data).expect("Unable to write file"); } 

Rust 1.0 et plus

Ces formulaires sont légèrement plus verbeux que les fonctions à une ligne qui allouent un Ssortingng ou un Vec pour vous, mais sont plus puissants en ce sens que vous pouvez réutiliser les données allouées ou les append à un object existant.

Lecture des données

La lecture d’un fichier nécessite deux éléments principaux: File et Read .

Lire un fichier sur une Ssortingng

 use std::fs::File; use std::io::Read; fn main() { let mut data = Ssortingng::new(); let mut f = File::open("/etc/hosts").expect("Unable to open file"); f.read_to_ssortingng(&mut data).expect("Unable to read ssortingng"); println!("{}", data); } 

Lire un fichier en tant que fichier Vec

 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()); } 

Ecrire un fichier

L’écriture d’un fichier est similaire, sauf que nous utilisons le trait Write et que nous écrivons toujours des octets. Vous pouvez convertir un Ssortingng / &str en octets avec 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 tamponnées

La communauté BufReader BufWriter à utiliser BufReader et BufWriter au lieu de lire directement à partir d’un fichier

Un lecteur (ou un enregistreur) en mémoire tampon utilise un tampon pour réduire le nombre de demandes d’E / S. Par exemple, il est beaucoup plus efficace d’accéder au disque une fois pour lire 256 octets au lieu d’accéder au disque 256 fois.

Cela étant dit, je ne crois pas qu’un lecteur / graveur en mémoire tampon sera utile lors de la lecture du fichier entier. read_to_end semble copier des données en gros morceaux, de sorte que le transfert peut déjà être naturellement fusionné en moins de requêtes d’E / S.

Voici un exemple d’utilisation en lecture:

 use std::fs::File; use std::io::{BufReader, Read}; fn main() { let mut data = Ssortingng::new(); let f = File::open("/etc/hosts").expect("Unable to open file"); let mut br = BufReader::new(f); br.read_to_ssortingng(&mut data).expect("Unable to read ssortingng"); println!("{}", data); } 

Et pour écrire:

 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 est plus utile lorsque vous souhaitez lire ligne par ligne:

 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); } }