Read an arbitrary number of bytes from type implementing Read

后端 未结 3 1408
南旧
南旧 2021-01-13 08:33

I have something that is Read; currently it\'s a File. I want to read a number of bytes from it that is only known at runtime (length prefix in a b

3条回答
  •  感动是毒
    2021-01-13 09:25

    1. Fill-this-vector version

    Your first solution is close to work. You identified the problem but did not try to solve it! The problem is that whatever the capacity of the vector, it is still empty (vec.len() == 0). Instead, you could actually fill it with empty elements, such as:

    let mut vec = vec![0u8; length];
    

    The following full code works:

    #![feature(convert)] // needed for `as_mut_slice()` as of 2015-07-19
    
    use std::fs::File;
    use std::io::Read;
    
    fn main() {
        let mut file = File::open("/usr/share/dict/words").unwrap();
        let length: usize = 100;
        let mut vec = vec![0u8; length];
        let count = file.read(vec.as_mut_slice()).unwrap();
        println!("read {} bytes.", count);
        println!("vec = {:?}", vec);
    }
    

    Of course, you still have to check whether count == length, and read more data into the buffer if that's not the case.


    2. Iterator version

    Your second solution is better because you won't have to check how many bytes have been read, and you won't have to re-read in case count != length. You need to use the bytes() function on the Read trait (implemented by File). This transform the file into a stream (i.e an iterator). Because errors can still happen, you don't get an Iterator but an Iterator>. Hence you need to deal with failures explicitly within the iterator. We're going to use unwrap() here for simplicity:

    use std::fs::File;
    use std::io::Read;
    
    fn main() {
        let file = File::open("/usr/share/dict/words").unwrap();
        let length: usize = 100;
        let vec: Vec = file
            .bytes()
            .take(length)
            .map(|r: Result| r.unwrap()) // or deal explicitly with failure!
            .collect();
        println!("vec = {:?}", vec);
    }
    

提交回复
热议问题