2017-02-12 4 views
6

バイナリファイル形式に書き込むときに、書き込まれたバイト数(たとえば、位置合わせ用)をチェックできるか、ネストされた関数が正しい量のデータを書き込んでいるかを確認するのに便利です。'std :: io :: Write'を使用するときに書き込まれるバイト数を記録する方法は?

どのくらい書き込まれているかを知るためにstd::io::Writeを調べる方法はありますか?そうでない場合は、ライターが何バイト書き込まれたかを追跡できるようにするには、どのような方法が良いでしょうか?

答えて

7

Writeは、2つの必要な方法: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()); 
} 

これらは、バイト数を返さないので、それはないデリゲートwrite_allまたはwrite_fmtに重要です。それらを委譲すれば、バイトを書き込んだり、追跡したりすることができなくなります。あなたが書くタイプがstd::io::Seekを実装する場合

+0

をこれも優れた答えは、正しいとの両方をマークするためにいいだろう! – ideasman42

+0

@ ideasman42「Seek」が実装されていない、または実装できない場合にも適用されるので、これを答えとしてマークしても構いません。 – wimh

+0

@wimhええ、わからない。受け入れは、彼らの特定のケースで最もOPを助けるものまでです。アップフォースは、将来の人々が有用と考える答えになる。 – Shepmaster

5

、あなたは現在の位置を取得するためにseekを使用することができます(ラップタイプがあまりにSeek実装している場合とstd::io::BufWriter

pos = f.seek(SeekFrom::Current(0))?; 

Seekstd::fs::Fileによって実装されます。


だから関数のシグネチャ:

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

fn my_write<W: Write>(f: &mut W) -> Result<(), Error> { ... } 

ニーズがSeek形質が追加されているために:

fn my_write<W: Write + Seek>(f: &mut W) -> Result<(), Error> { ... } 
関連する問題