C++读取BIN⽂件的⼀些问题
程序要求读取⼀个ARM的BIN⽂件,需要获取每⼀个字节,写了⼀个函数测试⼀下:
⽂件:
由于不熟悉,弄出了很多问题。相关问题如下:
1 BIN⽂件
fprintf格式BIN⽂件不以ASCII码存放数据,它将内存中数据存储形式不加转换地传送到磁盘⽂件,因此它⼜称为内存数据的映像⽂件。⽂件中的信息不是字符数据,⽽是字节中的⼆进制形式的信息,因此它⼜称为字节⽂件。
⽂本⼯具打开⼀个⽂件,如记事本,⾸先读取⽂件物理上对应的⼆进制⽐特流,再按⽤户选择的解码⽅式来解释这个流,再显⽰解释结果。如果记事本⽆论打开什么⽂件都按某种特定编码(如ASCII码),就可能出现乱码。
如上⾯的test.bin⽂件,⽤EmEditor直接打开,(其编码:GB2312),会提⽰某些字符⽆法⽤指定的编码进⾏转换。想要像上⾯这张图⽅便地查看16进制,就要选择以⼆进制⽅式打开(16进制试图),如果选择ASCII视图,也是乱码。
不管你怎么样,存储的都还是那个东西。我们看到的字符并不代表存储的是⼀个字符。如01000000按ASCII码解码,则对应是A,记事本可以显⽰A,但是也有可能只是⼀个4字节int数据的四分之⼀。不管是⼆进制⽂件,还是⽂本⽂件,都是⼀连串的0和1,但是打开⽅式不同,对于这些0和1的处理也就不同。如果按照⽂本⽅式打开,在打开的时候会进⾏translate,将每个字节转换成ASCII码,⽽以按照⼆进制⽅式打开的话,则不会进⾏任何的translate;⼆进制⽂件是按⼆进制的编码⽅式来存放⽂件的。例如,数5678的存储形式为:00010110 00101110 只占⼆个字节。⼆进制⽂件虽然也可在屏幕上显⽰,但其内容⽆法读懂。C系统在处理这些⽂件时,并不区分类型,都看成是字符流,按字节进⾏处理。输⼊输出字符流的开始和结束只由程序控制⽽不受物理符号(如回车符)的控制。因此也把这种⽂件称作“流式⽂件”。
2 C++ 读取
C++打开⽂件,以什么模式打开不重要,既改变不了⽂件本⾝的内容,也改变不了C/C++中系统函数的⼯作⽅式,所以只要关⼼这个⽂件⾥的数据内容本⾝是⼆进制格式还是⽂本格式,如果内容是⽂本格式的,就调⽤⽂本格式那⼀套函数,⽐如puts,gets,fscanf,fprintf,<<,>>等,如果内容是⼆进制格式的,你就调⽤⼆进制格式那⼀套函数,⽐如fread,ad(),ofstream.write()等。 只要保持⽂件内容与处理函数相对应相⼀致。
这个问题暂时没有遇到,因为打开时都指明了:ios::binary,调⽤的也是read(),先记下来以防以后出错。
C++读取BIN⽂件,可以⽤ifstream的read()。
原型: read( char *buffer, streamsize number );
有的⽂章⾥第⼀个参数是unsigned char* ,但是vs2015⾥看到的是char *。
buffer即指向缓冲区指针,number即读取字节数。
3 类型的转换
在类型的转换这上⾯绕了很久:
⾸先程序要求,我要⽤unsigned int类型存储每个字节,假设是k,read⽂件的第⼀个参数是char *,也就是说读取的⼀个字节的数据类型是char,假设⽤x存储,然⽽x直接赋值给k会出现错误。
每个数对应的是E3 A0 00 A0,(⼩端模式),
E3即1110 0011,扩展32位的话 1111 1111 1110 0011(我们看到的,存储的就是补码)
正好就是4294967267.
如果x是unsigned char,赋值给k就不会出错。
但是在read函数参数⾥要进⾏类型转换,即改成read((char*)&x, 1))
&x是(unsigned char *)强制指针类型转换成(char *),都是8位,对x没有区别,指针强制类型转换仅是将这个地址单元⾥存储的内容按不同的类型进⾏变量解释和读取,但如果这两个指针指向数据类型字
节数不同,数据就发⽣变化了。(如x:E3 还是1110 0011(不管解释成char 还是 unsigned char )但如果转换成 int类型 就会扩展x了)。
如此修改过后,结果正确了,如果不注意细节,就会有⼀些很绕⼈的错误:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论