2015-11-01 14 views
7

Desidero prelevare dati da posizioni casuali nel file di input e inviarli in sequenza al file di output. Preferibilmente, senza allocazioni non necessarie.Come eseguire il pipe in modo idiomatico/efficiente da Read + Seek a Write?

This is one kind of solution I have figured out:

use std::io::{ self, SeekFrom, Cursor, Read, Write, Seek }; 

#[test] 
fn read_write() { 
    // let's say this is input file 
    let mut input_file = Cursor::new(b"worldhello"); 
    // and this is output file 
    let mut output_file = Vec::<u8>::new(); 

    assemble(&mut input_file, &mut output_file).unwrap(); 

    assert_eq!(b"helloworld", &output_file[..]); 
} 

// I want to take data from random locations in input file 
// and output them sequentially to output file 
pub fn assemble<I, O>(input: &mut I, output: &mut O) -> Result<(), io::Error> 
    where I: Read + Seek, O: Write 
{ 
    // first seek and output "hello" 
    try!(input.seek(SeekFrom::Start(5))); 
    let mut hello_buf = [0u8; 5]; 
    try!(input.take(5).read(&mut hello_buf)); 
    try!(output.write(&hello_buf)); 

    // then output "world" 
    try!(input.seek(SeekFrom::Start(0))); 
    let mut world_buf = [0u8; 5]; 
    try!(input.take(5).read(&mut world_buf)); 
    try!(output.write(&world_buf)); 

    Ok(()) 
} 

Non preoccupiamoci su I/O latenza qui.

Domande:

  1. Condivide la ruggine stabile avere qualche aiuto per prendere x byte da un torrente e spingerli ad un altro corso d'acqua? O devo girare il mio?
  2. Se devo tirare il mio, forse c'è un modo migliore?
+2

Non correlato: cambia assemblare per usare '' ed è ancora più generico (consentendo gli oggetti tratto). – bluss

risposta

4

Stai cercando io::copy:

pub fn assemble<I, O>(input: &mut I, output: &mut O) -> Result<(), io::Error> 
    where I: Read + Seek, O: Write 
{ 
    // first seek and output "hello" 
    try!(input.seek(SeekFrom::Start(5))); 
    try!(io::copy(&mut input.take(5), output)); 

    // then output "world" 
    try!(input.seek(SeekFrom::Start(0))); 
    try!(io::copy(&mut input.take(5), output)); 

    Ok(()) 
} 

Se si guarda alla the implementation of io::copy, si può vedere che è simile al codice. Tuttavia, si prende cura di gestire più casi di errore:

  1. write fa non sempre scrivere tutto ciò che chiedete a!
  2. Una scrittura "interrotta" non è solitamente fatale.

Utilizza anche una dimensione di buffer più grande ma lo stack ancora alloca.

Problemi correlati