read_lines
Наївний підхід
Це може бути розумною першою спробою для першої реалізації початківця для читання рядків із файла.
#![allow(unused)]
fn main() {
use std::fs::read_to_string;
fn read_lines(filename: &str) -> Vec<String> {
let mut result = Vec::new();
for line in read_to_string(filename).unwrap().lines() {
result.push(line.to_string())
}
result
}
}
Оскільки метод lines() повертає ітератор по рядках у файлі,
ми також можемо виконати map inline і зібрати результати, отримуючи більш
стислий і плавний вираз.
#![allow(unused)]
fn main() {
use std::fs::read_to_string;
fn read_lines(filename: &str) -> Vec<String> {
read_to_string(filename)
.unwrap() // panic on possible file-reading errors
.lines() // split the string into an iterator of string slices
.map(String::from) // make each slice into a string
.collect() // gather them together into a vector
}
}
Зверніть увагу, що в обох прикладах вище ми маємо перетворити посилання &str,
повернуте з lines(), на тип-власник String, використовуючи відповідно .to_string()
і String::from.
Більш ефективний підхід
Тут ми передаємо володіння відкритим File структурам BufReader. BufReader використовує внутрішній
буфер, щоб зменшити проміжні виділення.
Ми також оновлюємо read_lines, щоб повертати ітератор замість виділення нових
об’єктів String у пам’яті для кожного рядка.
use std::fs::File;
use std::io::{self, BufRead};
use std::path::Path;
fn main() {
// File hosts.txt must exist in the current path
if let Ok(lines) = read_lines("./hosts.txt") {
// Consumes the iterator, returns an (Optional) String
for line in lines.map_while(Result::ok) {
println!("{}", line);
}
}
}
// The output is wrapped in a Result to allow matching on errors.
// Returns an Iterator to the Reader of the lines of the file.
fn read_lines<P>(filename: P) -> io::Result<io::Lines<io::BufReader<File>>>
where P: AsRef<Path>, {
let file = File::open(filename)?;
Ok(io::BufReader::new(file).lines())
}
Запуск цієї програми просто виводить рядки окремо.
$ echo -e "127.0.0.1\n192.168.0.1\n" > hosts.txt
$ rustc read_lines.rs && ./read_lines
127.0.0.1
192.168.0.1
(Зверніть увагу, що оскільки File::open очікує як аргумент узагальнений AsRef<Path>, ми визначаємо наш
узагальнений метод read_lines() з таким самим узагальненим обмеженням, використовуючи ключове слово where.)
Цей процес є більш ефективним, ніж створення String у пам’яті з усім вмістом файла. Це особливо
може спричиняти проблеми з продуктивністю під час роботи з більшими файлами.