首页 > 解决方案 > 如何将多个字节“读取”到“Vec”中?

问题描述

我有一种情况,我有一个目的地Vec,我想准确地将n我从Read对象中读取的字节推送到该目的地。

Read但是,通常处理切片。唯一使用的方法Vecread_to_end,但我需要将读数“绑定”到仅n字节。

到目前为止,我可以看到 3 种方法来实现这一点,但我不确定我是否遗漏了什么,或者哪一个是最好的(或至少是最不坏的):操场

read_to_end无论如何使用

这是迄今为止最短的,但它也涉及最多的 stdlib 理解,我不确定我是否完全/正确地掌握了语义:

fn read1<T: Read>(mut reader: T, n: usize, sink: &mut Vec<u8>) -> Result<()> {
    reader.take(n as u64).read_to_end(sink)?;
    Ok(())
}

如果这不是一个实用功能,我认为by_ref为了不消耗源阅读器也很有用?

扩展Vec并读入该缓冲区

这涉及更多,并且存在我们向其中添加完全无效数据Vec以便有适当的“切片”读取的问题:

fn read2<T: Read>(mut reader: T, n: usize, sink: &mut Vec<u8>) -> Result<()> {
    let before = sink.len();
    let after = sink.len() + n;
    sink.resize(after, 0);
    if let Err(e) = reader.read_exact(&mut sink[before..after]) {
        sink.resize(before, 0);
        return Err(e.into());
    }
    Ok(())
}

这假设read_exact并且resize(向下)不要惊慌。

使用本地缓冲区

这是最简单和最复杂的:重复读取数据到本地缓冲区,然后从本地缓冲区复制到输出 vec。

fn read3<T: Read>(mut reader: T, mut n: usize, sink: &mut Vec<u8>) -> Result<()> {
    let before = sink.len();
    let mut buf = [0;64];
    
    while n > 0 {
        let b = &mut buf[0..min(64, n)];
        if let Err(e) = reader.read_exact(b) {
            sink.resize(before, 0);
            return Err(e.into());
        }
        sink.extend(&*b);
        n -= b.len();
    }
    
    Ok(())
}

这是我会用较低级别的语言做的,但它会让人恶心。与版本 2 相比,它确实向输出 vec 添加了我们可能需要删除的数据(我在这里选择这样做,但可能存在不必要的情况),但与解决方案 2 不同的是,它向 vec 添加了部分数据,它是有效的数据。

标签: rustio

解决方案


推荐阅读