如何跟踪使用'std :: io :: Write'时写入的字节数?

ide*_*n42 6 io rust

当写入二进制文件格式时,能够检查已写入的字节数(例如用于对齐)或仅确保嵌套函数写入正确数量的数据非常有用.

有没有办法检查std::io::Write知道写了多少?如果没有,那么包装编写器的好方法是什么呢?它可以跟踪写入了多少字节?

She*_*ter 7

Write有两个必要的方法:write和flush.由于write已经返回写入的字节数,因此您只需跟踪:

use std::io::{self, Write};

struct ByteCounter<W> {
    inner: W,
    count: usize,
}

impl<W> ByteCounter<W>
    where W: Write
{
    fn new(inner: W) -> Self {
        ByteCounter {
            inner: inner,
            count: 0,
        }
    }

    fn into_inner(self) -> W {
        self.inner
    }

    fn bytes_written(&self) -> usize {
        self.count
    }
}

impl<W> Write for ByteCounter<W>
    where W: Write
{
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        let res = self.inner.write(buf);
        if let Ok(size) = res {
            self.count += size
        }
        res
    }

    fn flush(&mut self) -> io::Result<()> {
        self.inner.flush()
    }
}

fn main() {
    let out = std::io::stdout();
    let mut out = ByteCounter::new(out);
    writeln!(&mut out, "Hello, world! {}", 42).unwrap();
    println!("Wrote {} bytes", out.bytes_written());
}
Run Code Online (Sandbox Code Playgroud)

不委托write_all或write_fmt因为这些不返回字节数很重要.委托它们将允许写入字节而不是跟踪字节.


wim*_*ica 5

如果你写的类型实现std::io::Seek,你可以seek用来获取当前位置:

pos = f.seek(SeekFrom::Current(0))?;
Run Code Online (Sandbox Code Playgroud)

Seek由std::fs::File(std::io::BufWriter如果包装类型也实现Seek)实现.


所以功能签名:

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

fn my_write<W: Write>(f: &mut W) -> Result<(), Error> { ... }
Run Code Online (Sandbox Code Playgroud)

需要Seek添加特征:

fn my_write<W: Write + Seek>(f: &mut W) -> Result<(), Error> { ... }
Run Code Online (Sandbox Code Playgroud)