关于C++读入二进制文件要注意的问题(转自百度空间)
2011-04-01 00:45
267 查看
原文地址:http://apps.hi.baidu.com/share/detail/24190387
刚好遇见这个问题,记录下来备用!
关于C++读入二进制文件要注意的问题 今天帮一个网友调程序,其中涉及读入二进制文件(关于什么是二进制文件和文本文件,我就不在这里赘述了,百度一搜就知道了),很久没有用C++对文件进行操作了,有点手生,怎么调都运行不出想要的结果,一点一点的排除,最终把问题锁定在文件读入这一部分。
后来我把程序改成了fopen和fread这种C语言的函数,程序运行就正常了。难道是C++对二进制文件的读入存在bug?当然不是,C++ 这个发展了几十年、成千上万的程序员用的东西当然不会有这种低级错误,肯定是程序员自身的问题。后来我把程序改成了in.read(...)这种方式读入 数据,也成功了,这就说明不能用in>>ch[i]这种方式读入文件。但是为什么不能这么读呢?我写了程序研究了一下。
#include <iostream>
#include <fstream>
#include <iomanip>
using namespace std;
void init_array(char* ch, int length) //将数组全部置0
{
memset(ch, 0, length);
}
void show_array(char* ch, int length)
{
for(int i = 0; i < length; ++i)
{
cout<<setw(4)<<hex<<(int)ch[i];
}
cout<<endl<<endl;
}
int main()
{
char out[10]={0x31, 0x32, 0x0A/*换行*/, 0x0D/*回车*/,
0x20/*空格*/, 0x48, 0x3C, 0x09/*制表*/, 0x45, 0x55};
char in[10];
cout<<"二进制文件里的内容:"<<endl;
show_array(out, 10);
ofstream wf;
wf.open("text.dat", ios::out | ios::binary);
wf.write(out, 10);
wf.close();
init_array(in, 10);
ifstream rf1;
rf1.open("text.dat", ios::in | ios::binary);
rf1.read(in, 10);
rf1.close();
cout<<"ifstream.read() 读入结果:"<<endl;
show_array(in, 10);
init_array(in, 10);
ifstream rf2;
rf2.open("text.dat", ios::in | ios::binary);
int n = 0;
while(rf2 >> in[n++]);
rf2.close();
cout<<"ifstream>>in
读入结果:"<<endl;
show_array(in, 10);
system("pause");
return 0;
}
运行结果如图所示:
从运行结果就可以看出,用“>>”的这种方式没有读入0x0A、0x0D、 0x20、0x09这几个字符,而这几个字符正好是换行、回车、空格、制表符,也就是通常所说的空白字符。众所周知,cin>>默认是不读入 空白字符的,其实文件的“>>”读入方式也是如此,如果二进制文件的哪个字节恰好与空白字符的ASCII码相同,就会被舍弃,这一点是不期望 的,当文件较大时,遇到这种情况的概率是很高的。所以用“>>”读入二进制文件,读入的字节数会小于文件本身的字节数。
综上所述,用C++读入二进制文件时,不能用“>>”这种方式,要使用read()函数。
原始程序是这样的:
ifstream in("...", ios::binary);
while(in >> ch[i++]); //ch是字符数组,i初值为0
刚好遇见这个问题,记录下来备用!
关于C++读入二进制文件要注意的问题 今天帮一个网友调程序,其中涉及读入二进制文件(关于什么是二进制文件和文本文件,我就不在这里赘述了,百度一搜就知道了),很久没有用C++对文件进行操作了,有点手生,怎么调都运行不出想要的结果,一点一点的排除,最终把问题锁定在文件读入这一部分。
后来我把程序改成了fopen和fread这种C语言的函数,程序运行就正常了。难道是C++对二进制文件的读入存在bug?当然不是,C++ 这个发展了几十年、成千上万的程序员用的东西当然不会有这种低级错误,肯定是程序员自身的问题。后来我把程序改成了in.read(...)这种方式读入 数据,也成功了,这就说明不能用in>>ch[i]这种方式读入文件。但是为什么不能这么读呢?我写了程序研究了一下。
#include <iostream>
#include <fstream>
#include <iomanip>
using namespace std;
void init_array(char* ch, int length) //将数组全部置0
{
memset(ch, 0, length);
}
void show_array(char* ch, int length)
{
for(int i = 0; i < length; ++i)
{
cout<<setw(4)<<hex<<(int)ch[i];
}
cout<<endl<<endl;
}
int main()
{
char out[10]={0x31, 0x32, 0x0A/*换行*/, 0x0D/*回车*/,
0x20/*空格*/, 0x48, 0x3C, 0x09/*制表*/, 0x45, 0x55};
char in[10];
cout<<"二进制文件里的内容:"<<endl;
show_array(out, 10);
ofstream wf;
wf.open("text.dat", ios::out | ios::binary);
wf.write(out, 10);
wf.close();
init_array(in, 10);
ifstream rf1;
rf1.open("text.dat", ios::in | ios::binary);
rf1.read(in, 10);
rf1.close();
cout<<"ifstream.read() 读入结果:"<<endl;
show_array(in, 10);
init_array(in, 10);
ifstream rf2;
rf2.open("text.dat", ios::in | ios::binary);
int n = 0;
while(rf2 >> in[n++]);
rf2.close();
cout<<"ifstream>>in
读入结果:"<<endl;
show_array(in, 10);
system("pause");
return 0;
}
运行结果如图所示:
从运行结果就可以看出,用“>>”的这种方式没有读入0x0A、0x0D、 0x20、0x09这几个字符,而这几个字符正好是换行、回车、空格、制表符,也就是通常所说的空白字符。众所周知,cin>>默认是不读入 空白字符的,其实文件的“>>”读入方式也是如此,如果二进制文件的哪个字节恰好与空白字符的ASCII码相同,就会被舍弃,这一点是不期望 的,当文件较大时,遇到这种情况的概率是很高的。所以用“>>”读入二进制文件,读入的字节数会小于文件本身的字节数。
综上所述,用C++读入二进制文件时,不能用“>>”这种方式,要使用read()函数。
原始程序是这样的:
ifstream in("...", ios::binary);
while(in >> ch[i++]); //ch是字符数组,i初值为0
相关文章推荐
- 关于App涉及后台定位在审核时二进制文件被拒问题解决方案
- 关于在VI中查看BIN文件二进制值不对的问题
- 关于CI框架加入sphinx官方API接口文件的时候,需要注意的问题
- 【设计入门】新手初学设计应该注意哪些基础问题?——关于文件管理
- 关于制定so动态链接库文件需要注意的问题
- 关于VS2008问题“无法找到“XXX.exe”的调试信息,或者调试信息不匹配。未使用调试信息生成二进制文件。“
- [置顶]关于使用input type=file 标签上传文件的注意细节(上传文件 无法获取文件 问题)
- 关于标准C文件流读写问题:fopen,fread,fwrite,fclose的一些注意事项
- 关于genymotion 运行.so文件注意问题
- 关于使用input type=file 标签上传文件的注意细节(上传文件 无法获取文件 问题)
- 关于在创建文件时需要注意的问题
- wince中关于source文件中需要注意的问题
- 关于在类库下调用WebService和.edmx文件的问题
- 关于制作Cab文件中Unicode的问题
- 关于SpringBoot bean无法注入的问题(与文件包位置有关)改变自动扫描的包
- 关于oracle导入imp文件出现错误1435 用户不存在的 问题
- 关于Azure存储账户中存储虚拟机VHD文件的注意事项
- 关于C语言中的一些注意问题的小记之一----+号使用
- 关于UBOOT,LINUX内核编译,根文件系统的15个弱智问题(转)
- 关于matlab程序打包成exe可执行文件或者jar包的常见问题