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

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

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

这是一份处理正确的代码,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结束了

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
6、 函数模板和类模板 3 6.1函数模板 4 6.1.1为什么要有函数模板 4 6.1.2函数模板语法 5 6.1.3函数模板和模板函数 6 6.1.4函数模板做函数参数 6 6.1.5函数模板遇上函数重载 8 6.1.6 C++编译器模板机制剖析 10 6.2类模板 18 6.2.1为什么需要类模板 18 6.2.2单个类模板语法 18 6.2.3继承的类模板语法 20 6.2.4类模板语法知识体系梳理 21 6.2.5类模板的static关键字 23 6.3类模板在项目开发的应用 25 6.4作业 29 7、C++的类型转换 29 7.1 类型转换名称和语法 29 7.2 类型转换一般性介绍 29 7.3 典型案例 30 7.3.1 static_cast用法和reinterpret_cast用法 30 7.3.2 dynamic_cast用法和reinterpret_cast用法 31 7.3.3 const_cast用法 33 7.4 总结 33 8、异常处理机制专题 33 8.1 异常处理的基本思想 34 8.1.1传统错误处理机制 34 8.1.2异常处理的基本思想 34 8.2 C++异常处理的实现 35 8.2.1异常基本语法 35 8.2.2栈解旋(unwinding) 39 8.2.3异常接口声明 40 8.2.4异常类型和异常变量的生命周期 40 8.2.5异常的层次结构(继承在异常的应用) 46 8.3标准程序库异常 47 8.4训练强化 51 9 C++输入和输出流 51 9.1 I/O流的概念和流类库的结构 51 9.2标准I/O流 53 9.2.1标准输入流 55 9.2.2标准输出流 59 9.3文件I/O 66 9.3.1文件流类和文件流对象 66 9.3.2C++文件的打开与关闭 67 9.3.3C++对ASCII文件读写操作 69 9.3.4 C++二进制文件读写操作 74 9.4作业练习 75 10、STL实用技术专题 79 10.1 STL(标准模板库)理论基础 79 10.1.1基本概念 79 10.1.2容器 80 10.1.3迭代器 82 10.1.4算法 82 10.1.5C++标准库 82 10.1.6模板简要回顾 85 10.2容器 86 10.2.1 STL的string 86 10.2.2Vector容器 90 10.2.3Deque容器 96 10.2.4stack容器 101 10.2.5Queue容器 103 10.2.6List容器 105 10.2.7优先级队列priority_queue 110 10.2.8Set和multiset容器 111 10.2.9Map和multimap容器 118 10.2.10容器共性机制研究 123 10.2.11其他 124 10.3算法 125 10.3.1算法基础 125 10.3.2STL算法函数对象和谓词 138 10.3.3常用的遍历算法 148 10.3.4常用的查找算法 152 10.3.5常用的排序算法 154 10.3.6常用的拷贝和替换算法 156 10.3.7常用的算术和生成算法 157 10.3.8常用的集合算法 158 10.4 STL综合案例 159 10.4.1案例学校演讲比赛 159 10.4.2案例:足球比赛 161

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dxgzg

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值