迭代同一文件的行后,迭代文件的字节为空

问题描述 投票:2回答:1

我正在创建类似于wc命令的东西。计数行似乎工作正常,但计数字节总是返回0.计数单词也不起作用;输出似乎“挂起”就像是在等待某事。

我意识到它的制作方式(读取文件3次)并不是最佳的方法,但我只想要一个有效的简单例子

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

fn main() {
    let arg = &std::env::args()
        .nth(1)
        .expect("No file operand found")
        .to_owned();
    let file = File::open(arg).expect("Unable to open file for reading");

    let lines = count_lines(&file);
    print!("{} ", lines);
    let bytes = count_bytes(&file);
    println!("{}", bytes);
    let words = count_words(&file);
    print!("{} ", words);
}

fn count_lines(file: &File) -> u32 {
    let mut count: u32 = 0;
    BufReader::new(file).lines().for_each(|f| {
        if f.is_ok() {
            count += 1;
        }
    });

    count
}

fn count_bytes(file: &File) -> u32 {
    let mut count: usize = 0;
    BufReader::new(file).bytes().for_each(|f| {
        if f.is_ok() {
            count += 1;
        }
    });

    count as u32
}

fn count_words(file: &File) -> u32 {
    let mut count: u32 = 0;

    let mut buf: Vec<u8> = Vec::new();
    let mut reader = BufReader::new(file);
    while let Ok(_) = reader.read_until(b' ', &mut buf) {
        count += 1;
    }

    count
}
rust
1个回答
2
投票

您的问题是您打开文件一次,阅读完整的文件,然后假设它会被神奇地重置。

File有一个位置“指针”来知道下一个要读取的字节。读完一个字节后,该位置将加1,因此下一个读取调用将读取下一个字节而不是相同的字节。

你可以在调用File::seekcount_linescount_bytes之间使用count_words来改变这个位置。

use std::io::{Seek, SeekFrom};

fn main() {
    let arg = &std::env::args()
        .nth(1)
        .expect("No file operand found")
        .to_owned();
    let mut file = File::open(arg).expect("Unable to open file for reading");

    let lines = count_lines(&file);
    print!("{} ", lines);

    file.seek(SeekFrom::Start(0)).expect("Seek failed");
    let bytes = count_bytes(&file);
    println!("{}", bytes);

    file.seek(SeekFrom::Start(0)).expect("Seek failed");
    let words = count_words(&file);
    print!("{} ", words);
}

为了进一步解决您的代码,它不被视为非常“生锈”。使用Iterator::count可以简化您的手动计数。

fn count_lines(file: &File) -> u32 {
    BufReader::new(file).lines().count() as u32
}

fn count_bytes(file: &File) -> u32 {
    BufReader::new(file).bytes().count() as u32
}

你的count_words函数“挂起”的原因是你忽略了读取字节的数量。当read_until达到EOF(文件结束)时,它将返回0作为金额。你必须引入休息条件,例如

fn count_words(file: &File) -> u32 {
    let mut count: u32 = 0;

    let mut buf: Vec<u8> = Vec::new();
    let mut reader = BufReader::new(file);
    while let Ok(amount) = reader.read_until(b' ', &mut buf) {
        if amount == 0 {
            break
        }
        count += 1;
    }

    count
}

请注意,这是实现不是真的正确,因为"hello "(最后两个空格)将给你2而不是1,但这取决于你修复。确保add some tests确保一切正常。

© www.soinside.com 2019 - 2024. All rights reserved.