C++拷贝/复制一张图片 读写二进制文件

最近发现了自己网站一个bug(早发现了,一直没去深入探索原因),我网站的图标没了,按F12看看图标传过来了吗,发现传过来了。但为啥没显示出来百思不得其解,起初是怀疑图片是二进制文件保存的,所以按正常文件读写是不对的,想了之后决定用sendfile函数(Linux的一个系统函数,也叫零拷贝函数,没用过的同学可以翻翻man手册或者搜搜了解一下)发送二进制文件,对jpg、png来一个判断,然后sendfile直接发送,这样做起来改动是最少的,该完之后确实发现ok了,就放在那里没改了,最近要修改一下网站后台的源码,决定重新挖掘一下原因,记录一下这个bug。

如果读二进制文件,C语言的fopen,打开方式需要指定一个b,表示binary以二进制的文件打开。C++需要ios::binary来打开(在unix类系统中,ios::binary写不写貌似都可以,我查资料显示的是针对windows平台对换行符做了特殊的处理)
C++拷贝/复制一张图片 读写二进制文件_第1张图片

这是一份处理正确的代码,seekg移动到末尾,来看一下文件的大小,然后在移到起始位置来读文件。在进行写入文件

int succeful(){
	ifstream is("1.jpeg", ifstream::in | ios::binary);

	is.seekg(0, is.end);
	int length = is.tellg();
	is.seekg(0, is.beg);

	char * buffer = new char[length];

	is.read(buffer, length);


    ofstream os("111.jpeg",ofstream::out | ios::binary);

	if(!os.is_open()){
        cout << "写入文件未打开" << endl;
        return -1;
    }
    os.write(buffer,length);
    delete [] buffer;
	is.close();
	os.close();
}

上述代码是正确的,我们写C++都知道cout也是一个流对象,我可以cout << “XXXXXX”,上面写入文件os也是可以 os << buffer的,天真的我这么做了发现了又出bug了,拷贝文件失败了。为什么会失败捏?因为char*遇到’\0’是会自动停止输出的,而write指定输出长度所以就算遇到了‘\0’也不会停下来的

又解决了一个难题,你以为结束了吗?不并没有,我的网站用的是string类型读文件,而不是char*,当我把buffer赋值给string对象,天真的我以为一切正常,凌晨三点的我准备关机睡觉,结果一运行发现竟然是错的
改动如下:

string s = buffer;
	if(!os.is_open()){
        cout << "写入文件未打开" << endl;
        return -1;
    }
    // os.write(s.c_str(),length);
    // os.write(s.c_str(),s.size());
	os << s;

write也不对,size也不对、length也不对、os直接输出也不对,当时我内心为啥阿咋回事,我起初以为c_str()用的不对,后来忘了看那篇文章了,提了一句stirng构造函数,我就明白了,因为在构造string对象的时候char*遇到\0就结束了,所以string数据是不正确的,string s(buffer,length);改成这样子就OK了。string的小坑,之前确实没注意string的构造函数,也没注意到’\0’引发的问题

读写二进制文件

read二进制记住不能用strlen这样的函数来判断读取的字节数,可以用fstat函数获取一下文件大小,然后string构造的时候,string s(str,n),给s一个长度值,这样string构造的时候不会遇到\0结束了

你可能感兴趣的:(C++,c++)