2015-07-02 15 views
38

Với Rust tương đối mới, tôi đã thấy quá nhiều cách đọc và ghi tệp. Nhiều đoạn trích cực kỳ lộn xộn mà ai đó đã đưa ra cho blog của họ và 99% ví dụ tôi đã tìm thấy (ngay cả trên Stack Overflow) là từ các bản dựng không ổn định không còn hoạt động nữa. Bây giờ Rust ổn định, một đoạn trích đơn giản, dễ đọc, không hoảng loạn để đọc hoặc ghi tệp là gì?Cách đọc và ghi tập tin thực tế trong Rust 1.x là gì?

Đây là gần nhất tôi đã nhận được một cái gì đó mà hoạt động về đọc một tập tin văn bản, nhưng nó vẫn không biên dịch mặc dù tôi khá chắc chắn tôi đã bao gồm tất cả mọi thứ tôi cần phải có. Này được dựa tắt của một đoạn tôi tìm thấy trên Google+ của tất cả các nơi, và điều duy nhất tôi đã thay đổi là cái cũ BufferedReader tại là chỉ 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); 
    } 
} 

Trình biên dịch phàn nàn:

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() { 
    |>      ^^^^^ 

Nói tóm lại, những gì tôi đang tìm kiếm là:

  • ngắn gọn
  • dễ đọc
  • bao gồm tất cả các lỗi có thể
  • không hoảng sợ
+0

Bạn muốn đọc tệp như thế nào? Bạn có muốn nó theo từng dòng, như bạn đã hiển thị không? Bạn có muốn tất cả trong một chuỗi? Có nhiều cách để "đọc một tệp". – Shepmaster

+0

Dù cách nào cũng tốt. Tôi để nó mở một cách cố ý. Nếu nó thu thập tất cả thành một chuỗi, tách nó thành một Vec sẽ là tầm thường, và ngược lại. Tại thời điểm này trong tìm kiếm của tôi cho các giải pháp, tôi sẽ được hạnh phúc để chỉ nhìn thấy thanh lịch, up-to-date Rust tập tin I/O mã hoạt động. –

+1

Về lỗi tính trạng ('std :: io :: Read'), lưu ý rằng trong Rust bạn phải nhập các đặc điểm mà bạn mong muốn sử dụng * một cách rõ ràng *; Vì vậy, ở đây bạn đang thiếu một 'sử dụng std :: io :: Read' (mà có thể là một' sử dụng std :: io :: {Đọc, BufReader} 'để kết hợp hai sử dụng với nhau) –

Trả lời

49

Bạn cần hai miếng cốt lõi: FileRead.

Nếu bạn muốn đọc tất cả mọi thứ đến một 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); 
} 

Nếu bạn muốn đọc tất cả mọi thứ như một tập hợp các byte:

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

Không ai trong số các chức năng hoảng loạn trên riêng của họ, nhưng Tôi đang sử dụng expect vì tôi không biết loại xử lý lỗi nào sẽ phù hợp nhất với ứng dụng của bạn.

Đây là nhẹ hơn tiết hơn các phiên bản giả thuyết đó sẽ phân bổ một String hoặc Vec cho bạn, nhưng là mạnh hơn ở chỗ bạn có thể tái sử dụng dữ liệu được phân bổ hoặc thêm vào sau một đối tượng hiện có. Viết một wrapper nhỏ mà phân bổ các đối tượng cho bạn là tầm thường, và có thể là một bổ sung ergonomic trong tương lai.

Viết tệp giống nhau, ngoại trừ tệp luôn được thực hiện dưới dạng byte. Bạn có thể chuyển đổi một String/&str để byte với 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"); 
} 

tôi cảm thấy một chút của một push từ cộng đồng để sử dụng BufReaderBufWriter thay vì đọc trực tiếp từ một file

Một bộ đọc đệm (hoặc người viết) sử dụng bộ đệm để giảm số lượng yêu cầu IO. Ví dụ, nó hiệu quả hơn để truy cập đĩa một lần để đọc 256 byte thay vì truy cập đĩa 256 lần.

Điều đó đang được nói, tôi không tin rằng người đọc/người viết đã được đệm sẽ hữu ích khi đọc toàn bộ tệp.read_to_end dường như sao chép dữ liệu trong các phần hơi lớn, do đó quá trình chuyển có thể đã được kết hợp tự nhiên thành các yêu cầu IO ít hơn.

Dưới đây là một ví dụ của việc sử dụng nó:

use std::fs::File; 
use std::io::{Read, BufReader}; 

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

Và để viết:

use std::fs::File; 
use std::io::{Write, BufWriter}; 

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

Một BufReader là hữu ích hơn khi bạn muốn đọc line-by-line:

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

Hàng đêm Ru st, có chức năng một dòng cho việc đọc và viết:

#![feature(fs_read_write)] 

use std::fs; 

fn main() { 
    let data = fs::read_string("/etc/hosts").expect("Unable to open file"); 
    println!("{}", data); 
} 
#![feature(fs_read_write)] 

use std::fs; 

fn main() { 
    let data = fs::read("/etc/hosts").expect("Unable to open file"); 
    println!("{}", data.len()); 
} 
#![feature(fs_read_write)] 

use std::fs; 

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

tôi mong đợi này để trở thành lựa chọn phổ biến khi chúng được ổn định.

+0

Tôi không thực sự có nhiều để căn cứ điều này, nhưng trong khi nghiên cứu này tôi cảm thấy một chút của một đẩy từ cộng đồng để sử dụng BufReader và BufWriter thay vì đọc trực tiếp từ một tập tin vào một chuỗi. Bạn có biết nhiều về những đồ vật này hay những ưu và nhược điểm của việc sử dụng chúng trên phiên bản "cổ điển hơn" mà bạn đã thể hiện trong câu trả lời của mình không? –

+0

Thật là một ví dụ đơn giản, đẹp mắt, tôi đã tìm kiếm hàng giờ cho sth như thế này. Cảm ơn. – rebeling

Các vấn đề liên quan