在 Rust 中,我想从流或文件中读取数据以填充缓冲区,并检测 EOF

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

在 Rust 中,我想读入(使用 BufReader)到缓冲区数组中以填充它。我想读取确切的字节数,除了 EOF 的情况,在这种情况下读取较少的字节数就可以了。我自己实现了一个辅助方法,如下所示,并且有效。但是我想知道是否没有方便的方法可以做到这一点。

pub fn read_fully<R: Read>(read: &mut R, buffer: &mut [u8]) -> Result<usize, Error> {
    let mut count: usize = 0;
    loop {
        let r = read.read(&mut buffer[count..])?;
        if r == 0 {
            return Ok(count);
        }
        count += r;
    }
}

我发现每个现有的方法似乎都存在问题:

  • “read”可能读得更少(例如对于标准输入)。
  • “read_exact”与 EOF 不能很好地配合。
  • “read_to_end”需要一个 Vec 而不是数组,并且会读取所有内容,可能会扩展向量。
rust io
2个回答
0
投票

这是一个想法,我不确定它比你的更好,但它也有效:

pub fn read_fully<R: Read>(read: &mut R, buffer: &mut [u8]) -> Result<usize, Error> {
    let mut data = Vec::with_capacity(buffer.len());
    read.take(buffer.len().try_into().unwrap())
        .read_to_end(&mut data)?;
    buffer[..data.len()].copy_from_slice(&data);
    Ok(data.len())
}

效率可能会低很多。是否更清晰由您决定。


0
投票

看来ErrorKind::Interrupted应该被忽略。所以解决方案将变成:

pub fn read_fully<R: Read>(read: &mut R, buffer: &mut [u8]) -> Result<usize, Error> {
    let mut count: usize = 0;
    loop {
        let r = read.read(&mut buffer[count..]);
        match r {
            Ok(0) => {
                return Ok(count)
            },
            Ok(x) => {
                count += x
            },
            Err(e) => {
                if e.kind() == ErrorKind::Interrupted {
                    // retry
                } else {
                    return Err(e);
                }
            }
        };
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.