如何使用Rust创建二进制文件?

13
我可以用 Rust 将二进制代码写入文件。但是,当我创建一个文件时,创建的文件是文本文件,而不是二进制文件。 我可以用 C++ 创建二进制文件,就像这样:
ofstream is("1.in", ofstream::binary | ofstream::out | ofstream:: trunc);

在Rust中如何实现呢?这是我的尝试:
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
    );
}

运行此代码后,它将200个u32整数二进制数字写入tableIndexName文件。但是,该文件的大小不是800字节。它大约是4KB。


2
你能分享一下你目前用来读写文件的示例代码吗?你觉得这个文件不是“二进制”的原因是什么? - harmic
@harmic 你好,谢谢回复。我在我的问题中添加了一些代码。 - Yen Chun Lee
欢迎来到 Stack Overflow!在 Rust 中,惯用的命名方式是:变量、方法、宏和字段使用 snake_case;类型和枚举变体使用 UpperCamelCase;静态变量和常量使用 SCREAMING_SNAKE_CASE。请使用 file_writetable_index_name - Shepmaster
1个回答

34
Rust的std::fs::File没有文本或二进制模式打开文件的概念。所有文件都被视为“二进制”文件,不执行换行符和回车符等字符的转换。
你的问题源于使用write!宏。此宏用于将数据格式化为可打印格式,如果要写入二进制数据,则不应使用该宏。实际上,您使用的{:b}格式说明符将把值转换为ASCII 10字符的可打印二进制字符串。
相反,使用trait std::io::Write提供的函数。这个trait直接由File实现,或者您可以使用BufWriter来获得更好的性能。
例如:在这里我使用write_allu8的slice写入文件,然后使用read_to_end将同一文件读回到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(())
}

1
为什么在main函数内部有不必要的花括号? - Shepmaster
10
@Shepmaster 第一对大括号确保在再次打开和读取文件之前关闭文件。这并不是严格必要的,因为代码使用了非缓冲的I/O,所以即使在文件关闭之前也可以读取文件内容。然而,就这个问题而言,这有点不太相关,所以我认为包括大括号的版本更加清晰易懂。 - Sven Marnach

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接