2015-05-23 12 views
8

Ho una struttura con uno BufStream<T> dove T: Read+Write. BufStream può essere un TcpStream e mi piacerebbe leggere n byte da esso. Non una quantità fissa di byte in un buffer predefinito, ma ho una stringa/stream che indica il numero di byte da leggere successivamente.Come leggere un numero specifico di byte da uno stream?

C'è un bel modo per farlo?

risposta

3

Sembra che si desidera Read::take e Read::read_to_end:

use std::io::prelude::*; 
use std::io::BufReader; 
use std::str; 

fn read_n<R>(reader: R, bytes_to_read: u64) -> Vec<u8> 
where 
    R: Read, 
{ 
    let mut buf = vec![]; 
    let mut chunk = reader.take(bytes_to_read); 
    // Do appropriate error handling for your situation 
    let n = chunk.read_to_end(&mut buf).expect("Didn't read enough"); 
    assert_eq!(bytes_to_read as usize, n); 
    buf 
} 

fn main() { 
    let input_data = b"hello world"; 
    let mut reader = BufReader::new(&input_data[..]); 

    let first = read_n(&mut reader, 5); 
    let _ = read_n(&mut reader, 1); 
    let second = read_n(&mut reader, 5); 

    println!(
     "{:?}, {:?}", 
     str::from_utf8(&first), 
     str::from_utf8(&second) 
    ); 
} 
+0

Grazie .. non serve() consumare il lettore? Il mio caso è che ho un tcpstream (parte di una struct) da cui leggo le righe. A volte in mezzo non ho bisogno di leggere una riga ma una quantità specifica di byte. Dopo avrò bisogno di leggere di nuovo le righe ... – buster

+1

Lo fa, ma "il lettore" può essere un '& mut R ', un riferimento temporaneo mutevole a un altro lettore. Take utilizza un'API di valore in modo che tutti i casi d'uso siano supportati. Questo modello appare in alcuni angoli diversi della ruggine. – bluss

+0

@buster come sottolinea bluss, '& mut R' implementa anche la caratteristica' Leggi '. Il mio esempio lo usa con buoni risultati - è per questo che passo in '& mut reader' nel metodo principale dell'esempio. – Shepmaster

4

Dal Rust 1.6, Read::read_exact può essere usato per fare questo. Se bytes_to_read è il numero di byte che è necessario leggere, possibilmente determinato in fase di esecuzione, e reader è il flusso di leggere da:

let mut buf = vec![0u8; bytes_to_read]; 
reader.read_exact(&mut buf)?; 

La parte che non era chiaro per me dalla documentazione read_exact era che il bersaglio il buffer può essere assegnato dinamicamente allo Vec.

Grazie alla comunità Rust Gitter per avermi indicato questa soluzione.

Problemi correlati