我试图读取文件的一些原始字节,所以我查看了文档并将一个函数放在一起,看起来应该将字节读入向量并从中读取32位整数头。
fn filetobytes(name: &'static str) -> Vec<u8> {
let file = File::open(name).expect("No such file");
let filebytes: Vec<u8> = file.bytes().map(|readbyte| readbyte.unwrap()).collect();
return filebytes;
}
fn parse_int(index: usize, vector: &Vec<u8>) -> u32 {
let mut num: u32 = 0;
for i in 0..4 {
num = num << 8;
num = num | ((vector[index + i] as u32) & 0xff);
println!("Byte is {:x}", vector[index + i]);
}
return num;
}
fn main() {
let filebytes = filetobytes("diddy.h");
println!("0x{:x}", parse_int(0, &filebytes));
}
然后我试图前进,但很快就发现我的逻辑都没有起作用。在做了一些嗅探后,我发现我没有按照预期的顺序获取字节。例如,上面的代码(分别打印前四个字节然后合成为整数)产生以下输出
Byte is 23
Byte is 64
Byte is 65
Byte is 66
0x23646566
如果我在hexdump
上diddy.h
,我会得到以下输出。
0000000 6423 6665 6e69 2065 4944 4444 5f59 4957
0000010 5444 2048 3031 0a35 6423 6665 6e69 2065
0000020 4944 4444 5f59 4548 4749 5448 3120 3035
0000030 630a 6e6f 7473 7520 736e 6769 656e 2064
0000040 6873 726f 2074 6964 6464 5f79 6164 6174
0000050 315b 3735 3035 3b5d 000a
0000059
奇怪的是,似乎vector[0]
访问字节1,vector[1]
访问字节0,vector[2]
获取字节3,vector[3]
获取字节2,依此类推。< / p>
我可能做了什么导致此行为,以及如何解决此问题?
答案 0 :(得分:2)
Jan Zerebecki的评论是正确的,但可能会受益于一点点阐述:
Hexdump默认将文件显示为16位整数值的集合。他们似乎处于'错误的顺序'的原因是Hexdump尊重主机的字节序,并且你在小端机器上运行它。
让我们使用hexdump的自定义输出格式选项做一个例子。首先,我们将编写一个xxd兼容的hexdump,并将其转换为二进制。
$ echo 00000000: 01 23 45 67 89 ab cd ef > num.hex
$ xxd -r num.hex num.bin
然后我们将向自己证明hexdump 可以使用规范输出模式读取它:
$ hexdump -C num.bin
00000000 01 23 45 67 89 ab cd ef |.#Eg....|
00000008
接下来,我们将使用它相当模糊的输出格式选项将值显示为十六进制,但一次选择1,2,4和8个字节:
$ hexdump -e '1/1 "%02x "' num.bin
01 23 45 67 89 ab cd ef
$ hexdump -e '1/2 "%02x "' num.bin
2301 6745 ab89 efcd
$ hexdump -e '1/4 "%02x "' num.bin
67452301 efcdab89
$ hexdump -e '1/8 "%02x "' num.bin
efcdab8967452301
你看到的是hexdump将这些字节解释为不同大小的小端整数,并执行将最高位数放在左边所需的字节交换...我们想要表示数字的方式。 / p>
答案 1 :(得分:0)
似乎hexdump
实际上是以错误的顺序显示的。 hexdump -C
正确读取。
答案 2 :(得分:-1)
我建议使用Bytes
create,您应该能够将parse_int
函数编写为:
use bytes::{ByteOrder, BigEndian, LittleEndian};
fn parse_int(index: usize, vector: &[u8]) -> u32 {
// BigEndian/Little Edian here should be determined by the file format, NOT the system format
LittleEndian::read_u32(&vector[index])
}