Christopher Reid
Christopher Reid

Reputation: 4484

Convert image to bytes and then write to new file

I'm trying to take an image that is converted into a vector of bytes and write those bytes to a new file. The first part is working, and my code is compiling, but the new file that is created ends up empty (nothing is written to it). What am I missing?

Is there a cleaner way to convert Vec<u8> into &[u8] so that it can be written? The way I'm currently doing it seems kind of ridiculous...

use std::os;
use std::io::BufferedReader;
use std::io::File;
use std::io::BufferedWriter;

fn get_file_buffer(path_str: String) -> Vec<u8> {
    let path = Path::new(path_str.as_bytes());
    let file = File::open(&path);
    let mut reader = BufferedReader::new(file);
    match reader.read_to_end() {
        Ok(x) => x,
        Err(_) => vec![0],
    }
}

fn main() {
    let file = get_file_buffer(os::args()[1].clone());

    let mut new_file = File::create(&Path::new("foo.png")).unwrap();
    let mut writer = BufferedWriter::new(new_file);

    writer.write(String::from_utf8(file).unwrap().as_bytes()).unwrap();
    writer.flush().unwrap();
}

Upvotes: 1

Views: 4964

Answers (1)

Chris Morgan
Chris Morgan

Reputation: 90742

Given a Vec<T>, you can get a &[T] out of it in two ways:

  • Take a reference to a dereference of it, i.e. &*file; this works because Vec<T> implements Deref<[T]>, so *file is effectively of type [T] (though doing that without borrowing it, i.e. &*file, is not legal).

  • Call the as_slice() method.

As the BufWriter docs say, “the buffer will be written out when the writer is dropped”, so that writer.flush().unwrap() is not strictly necessary, serving only to make handling of errors explicit.

But as for the behaviour you describe, that I mostly do not observe. So long as you do not encounter any I/O errors, the version not using the String dance will work fine, while with the String dance it will panic if the input data is not legal UTF-8 (which if you’re dealing with images it probably won’t be). String::from_utf8 returns None in such cases, and so unwrapping that panics.

Upvotes: 4

Related Questions