2017-02-12 43 views
6

İkili bir dosya biçiminde yazarken, kaç bayt yazıldığını (örneğin hizalama için) veya iç içe geçmiş işlevlerin doğru miktarda veri yazdığından emin olmak için kullanışlıdır.'std :: io :: Write' kullanırken kaç bayt yazılır?

Ne kadar yazıldığını öğrenmek için std::io::Write'u denetlemenin bir yolu var mı? Değilse, yazarın ne kadar çok sayıda bayt yazıldığını izleyebilmesi için iyi bir yaklaşım ne olurdu?

cevap

7

Write, iki gerekli yönteme sahiptir: write ve flush. Bu bayt sayısını döndürmez çünkü

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()); 
} 

O değil temsilci write_all veya write_fmt önemlidir: write zaten yazılı bayt sayısını döndürür yana, sadece o parça. Onları yetkilendirmek, baytların yazılmasına ve izlenmemesine izin verir. Yazdığınız tip std::io::Seek uygular Eğer

+0

Bu mükemmel bir cevap da her ikisi olarak doğru işaretlemek için güzel olurdu olduğunu! – ideasman42

+0

@ ideasman42 Eğer bunu '' Ara '' uygulanmadıysa veya uygulanamazsa da uygulayacağından, bunu yanıt olarak işaretlerseniz umursamıyorum. – wimh

+0

@wimh eh, bilmiyorum. Kabul etmek, OP'ye en çok hangi durumda yardımcı olursa olsun. Destekler gelecekteki kişilerin faydalı bulduğu cevaplara gelir. – Shepmaster

5

, geçerli konumunu almak için seek kullanabilirsiniz: (sarılmış tip çok Seek uygulaması halinde ve std::io::BufWriter)

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

Seekstd::fs::File tarafından uygulanmaktadır.


Yani işlev imzası:

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

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

İhtiyaçları Seek özelliği var eklendi:

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