Avec 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 inventé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 de code simple, lisible et sans panique pour lire ou écrire des fichiers?
C'est ce qui se rapproche le plus de quelque chose qui fonctionne en termes de lecture d'un fichier texte, mais il n'est toujours pas compilé même si je suis assez 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 lieux, et la seule chose que j'ai changé 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::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() {
|> ^^^^^
Pour résumer, ce que je recherche c'est:
- brièveté
- lisibilité
- couvre toutes les erreurs possibles
- ne panique pas
std::io::Read
), notez que dans Rust, vous devez importer les traits que vous prévoyez d'utiliser explicitement ; il vous manque donc ici unuse std::io::Read
(qui pourrait être unuse std::io::{Read,BufReader}
pour fusionner les deux utilisations ensemble)Réponses:
Aucune des fonctions que je montre ici ne panique d'elles-mêmes, mais j'utilise
expect
parce que je ne sais pas quel type de gestion des erreurs conviendra le mieux à votre application. Allez lire la rouille Langage de programmation de » chapitre sur la gestion des erreurs pour comprendre comment gérer correctement l' échec 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 sur une ligne pour la lecture et l'écriture.
Lire un fichier dans un
String
Lire un fichier en tant que
Vec<u8>
Ecrire un fichier
Rust 1.0 et versions ultérieures
Ces formulaires sont légèrement plus détaillés que les fonctions sur une ligne qui allouent un
String
ouVec
pour vous, mais sont plus puissants en ce sens que vous pouvez réutiliser des données allouées ou les ajouter à un objet existant.Lecture des données
La lecture d'un fichier nécessite deux éléments essentiels:
File
etRead
.Lire un fichier dans un
String
Lire un fichier en tant que
Vec<u8>
Ecrire un fichier
L'écriture d'un fichier est similaire, sauf que nous utilisons le
Write
trait et que nous écrivons toujours des octets. Vous pouvez convertir unString
/&str
en octets avecas_bytes
:E / S tamponnées
Un lecteur (ou enregistreur) tamponné 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 / écrivain tamponné sera utile lors de la lecture du fichier entier.
read_to_end
semble copier les données en morceaux assez volumineux, de sorte que le transfert peut déjà être naturellement fusionné en moins de demandes d'E / S.Voici un exemple d'utilisation pour la lecture:
Et pour écrire:
A
BufReader
est plus utile lorsque vous souhaitez lire ligne par ligne:la source
b"foobar"
est un littéral pour créer une référence à un tableau d'octets (&[u8; N]
). En tant que tel, il est immuable. Il ne vous donne rien que vous ne puissiez pas faire de manière plus simple.Vec<u8>
pour lire et écrire. Ce sont des octets bruts.