Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a binary file with Rust?

I can write binary code to file with Rust. However, when I create a file, the file created is a text file, not binary. I can create a binary file with C++ like this:

ofstream is("1.in", ofstream::binary | ofstream::out | ofstream:: trunc);

How about in Rust? This is my attempt:

struct IndexDataStructureInt {
    row: u32,
    key_value: u32,
}

let mut index_arr: Vec<IndexDataStructureInt> = Vec::new();
// doing something push 100 IndexDataStructureInt to index_arr
let mut fileWrite = File::create(tableIndexName).unwrap();
for i in 0..index_arr.len() {
    write!(
        fileWrite,
        "{:b}{:b}",
        index_arr[i].row, index_arr[i].key_value
    );
}

After running this code, it writes 200 u32 integer binary number to the file tableIndexName. However, the file size is not 800bytes. It is about 4KB.

like image 791
Yen Chun Lee Avatar asked Dec 18 '18 04:12

Yen Chun Lee


1 Answers

Rust's std::fs::File does not have a concept of opening files in text or binary mode. All files are opened as "binary" files, and no translation of characters such as line feed and carriage return is performed.

Your problem stems from using the write! macro. This macro is for formatting data into printable format, and should not be used if you want to write binary data. In fact the {:b} format specifier you have used will convert the value into a printable binary string of ASCII 1 and 0 characters.

Instead, use the functions provided by trait std::io::Write. This trait is implemented directly by File, or you can use a BufWriter for potentially better performance.

For example: here I am using write_all to write a slice of u8 to a file, then using read_to_end to read the same file back into a Vec.

use std::fs::File;
use std::io::prelude::*;

fn main() -> std::io::Result<()> {
    {
        let mut file = File::create("test")?;
        // Write a slice of bytes to the file
        file.write_all(&[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])?;
    }

    {
        let mut file = File::open("test")?;
        // read the same file back into a Vec of bytes
        let mut buffer = Vec::<u8>::new();
        file.read_to_end(&mut buffer)?;
        println!("{:?}", buffer);
    }

    Ok(())
}
like image 131
harmic Avatar answered Oct 25 '22 00:10

harmic