Com o Rust sendo relativamente novo, já vi muitas maneiras de ler e gravar arquivos. Muitos são trechos extremamente confusos que alguém criou para seu blog, e 99% dos exemplos que encontrei (mesmo no Stack Overflow) são de versões instáveis que não funcionam mais. Agora que o Rust está estável, o que é um snippet simples, legível e sem pânico para ler ou gravar arquivos?
Este é o mais próximo que cheguei de algo que funciona em termos de leitura de um arquivo de texto, mas ainda não está compilando, mesmo tendo certeza de que incluí tudo o que deveria ter. Isso se baseia em um snippet que encontrei no Google+ de todos os lugares, e a única coisa que mudei é que o antigo BufferedReader
agora é apenas 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);
}
}
O compilador reclama:
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, o que estou procurando é:
- brevidade
- legibilidade
- cobre todos os erros possíveis
- não entra em pânico
std::io::Read
), observe que no Rust você deve importar as características que espera usar explicitamente ; Assim, aqui você está faltando umuse std::io::Read
(o que poderia ser umuse std::io::{Read,BufReader}
a se aglutinar os dois usos em conjunto)Respostas:
Nenhuma das funções que mostro aqui entra em pânico por conta própria, mas estou usando
expect
porque não sei que tipo de tratamento de erros se encaixará melhor em seu aplicativo. Leia o capítulo da Linguagem de programação Rust sobre tratamento de erros para entender como lidar adequadamente com falhas em seu próprio programa.Ferrugem 1.26 em diante
Se você não deseja se preocupar com os detalhes subjacentes, existem funções de uma linha para leitura e gravação.
Leia um arquivo para um
String
Leia um arquivo como
Vec<u8>
Escreva um arquivo
Rust 1.0 em diante
Esses formulários são um pouco mais detalhados do que as funções de uma linha que alocam um
String
ouVec
para você, mas são mais poderosas, pois você pode reutilizar dados alocados ou anexar a um objeto existente.Lendo dados
A leitura de um arquivo requer duas partes principais:
File
eRead
.Leia um arquivo para um
String
Leia um arquivo como
Vec<u8>
Escreva um arquivo
Escrever um arquivo é semelhante, exceto que usamos a
Write
característica e sempre escrevemos bytes. Você pode converter umString
/&str
para bytes comas_bytes
:E / S com buffer
Um leitor (ou gravador) em buffer usa um buffer para reduzir o número de solicitações de E / S. Por exemplo, é muito mais eficiente acessar o disco uma vez para ler 256 bytes em vez de acessar o disco 256 vezes.
Dito isto, não acredito que um leitor / gravador em buffer seja útil ao ler o arquivo inteiro.
read_to_end
parece copiar dados em partes um pouco grandes, portanto a transferência já pode ser naturalmente combinada em menos solicitações de E / S.Aqui está um exemplo de como usá-lo para leitura:
E para escrever:
A
BufReader
é mais útil quando você deseja ler linha por linha:fonte
b"foobar"
é um literal para criar uma referência a uma matriz de bytes (&[u8; N]
). Como tal, é imutável. Não há nada que você não possa fazer de uma maneira mais simples.Vec<u8>
para leitura e escrita. Esses são bytes brutos.