【C++】二进制文件拷贝及异常处理详解

一.知识点

异常捕捉机制:

一旦执行throw立刻转到catch,不再进行throw下面内容;

可设置不同类型throw值,但一次只能throw一个值, 与return类似

若一个类型有多个值,需拷贝,可动态内存分配后指针传递, 但麻烦. 通常直接const char* err接收即可

...throw "肉肉好帅!";
...throw "肉肉好傻!";
...throw "肉肉好萌!";

try(){
    ...
}
catch(const char* err){
    cout<< err <<endl;
}

catch顺次进行,只执行一个匹配分支;catch(…)通配。

如果throw float无匹配,会中断(缺省功能会调用abort终止程序),并显示Microsoft C++异常:内存位置xxxxxx处的float

最近的catch才能拿到throw,若最近的catch再throw,才会throw给次近的catch

throw;上次接到啥就扔啥.要是没接到就出错!

一般只throw异常!

二.示例

#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <vld.h>
using namespace std;
#define BUFFER_SIZE 1024//字节数
#define ELEMENT_SIZE 1
class Beauty {
public:
	Beauty() {}
	~Beauty() {}
	Beauty(const Beauty& other) {}
};
//c++二进制拷贝
void cppCopyBinary(const char* dest, const char* src) {//无法检测是否出现错误..
	std::ifstream input(src, ios::binary);
	std::ofstream output(dest, ios::binary);

	output << input.rdbuf();// read binary读取input
}
//c二进制拷贝
string cCopyBinary1(const char* dest, const char* src) {
	FILE* destF_p = NULL, * srcF_p = NULL;
	fopen_s(&srcF_p, src, "rb");// read binary
	if (!srcF_p) {
		return "源文件打开失败!";
	}

	fopen_s(&destF_p, dest, "wb");// write binary
	if (!destF_p) {
		fclose(srcF_p);
		return "目标文件打开失败!";
	}

	char buffer[BUFFER_SIZE];
	int readLen = fread_s(buffer, BUFFER_SIZE, ELEMENT_SIZE, BUFFER_SIZE, srcF_p);
	if (readLen <= 0) {
		fclose(srcF_p);
		fclose(destF_p);
		return "源文件读取失败!";
	}
	int writeLen = fwrite(buffer, ELEMENT_SIZE, readLen, destF_p);
	if (readLen != writeLen) {
		fclose(srcF_p);
		fclose(destF_p);
		return "目标文件拷贝失败!";
	}
	fclose(srcF_p);
	fclose(destF_p);
	return "成功!";
}
void cCopyBinary2(const char* dest, const char* src) {
	FILE* destF_p = NULL, * srcF_p = NULL;
	fopen_s(&srcF_p, src, "rb");
	if (!srcF_p) {
		throw "源文件打开失败!";
	}

	fopen_s(&destF_p, dest, "wb");
	if (!destF_p) {
		fclose(srcF_p);
		throw "目标文件打开失败!";
	}

	char buffer[BUFFER_SIZE];
	int readLen = fread_s(buffer, BUFFER_SIZE, ELEMENT_SIZE, BUFFER_SIZE, srcF_p);
	if (readLen <= 0) {
		fclose(srcF_p);
		fclose(destF_p);
		throw "源文件读取失败!";
	}
	int writeLen = fwrite(buffer, ELEMENT_SIZE, readLen, destF_p);
	if (readLen != writeLen) {
		fclose(srcF_p);
		fclose(destF_p);
		throw "目标文件拷贝失败!";
	}
	fclose(srcF_p);
	fclose(destF_p);
	throw "成功!";
}

void cCopyBinary3(const char* dest, const char* src) throw(char, int)//最好异常接口声明下,虽然C11编译器检测不出来!但可以起到提示/保证作用
{
	FILE* destF_p = NULL, * srcF_p = NULL;
	fopen_s(&srcF_p, src, "rb");
	if (!srcF_p) {
		//throw Beauty();
		throw string("源文件打开失败!");
	}

	fopen_s(&destF_p, dest, "wb");
	if (!destF_p) {
		fclose(srcF_p);
		throw new string("目标文件打开失败!");
	}

	char buffer[BUFFER_SIZE];
	int readLen = fread_s(buffer, BUFFER_SIZE, ELEMENT_SIZE, BUFFER_SIZE, srcF_p);
	if (readLen <= 0) {
		fclose(srcF_p);
		fclose(destF_p);
		throw new string("源文件读取失败!");
	}
	int writeLen = fwrite(buffer, ELEMENT_SIZE, readLen, destF_p);
	if (readLen != writeLen) {
		fclose(srcF_p);
		fclose(destF_p);
		throw - 1;
	}
	fclose(srcF_p);
	fclose(destF_p);
	throw 0;
}
//可以多次扔
void twoTimes() {
	try {
		cCopyBinary1("D:/tmp/dest.txt", "D:/tmp/src.txt");
	}
	catch (...) {
		throw;
	}
}
int main() {

	cppCopyBinary("dest.txt", "src.txt");
	cout << cCopyBinary1("D:/tmp/dest.txt", "D:/tmp/src.txt") << endl;//注意只有硬盘名后加冒号


	cout << "throw char,形参char*,实参char*申请内存,被赋值:" << endl;
	try {
		twoTimes();
	}
	catch (const char* err) {// "xxxx"传递值类型为char不能传给string
		cerr << err << endl;
	}

	cout << "throw new string/new char(char),形参string*,直接输出:";//创建new异常元素
	try {
		cCopyBinary3("D:/tmp/dest.txt", "D:/tmp/src.txt");
	}
	catch (Beauty& beauty) {
		cout << "捕捉到类Beauty异常!" << endl;
	}
	catch (string* err) {//err相当于处于缓冲区,需要再分配动态内存至error
		cout << "捕捉到字符串异常:" << err->c_str() << endl;
		delete err;
	}
	catch (int n) {
		if (!n) {//数字可直接传值
			cout << "捕捉到数字0:" << "成功!" << endl;
		}
	}
	catch (string err)
	{
		cout << "捕捉到string异常" << endl;
	}
	return 0;
}

//最佳方式:int直接扔
//字符串直接"xxx",const char*接 		(也可string()初始化,string接;若new string初始化,string *接,需记得再delete err;)
//类直接Beauty()初始化,Beauty&接;	    (若new Beauty则指针接,记得释放)

三个函数的区别:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-elmPEvuL-1587300702380)(C:\Users\Dell\AppData\Roaming\Typora\typora-user-images\image-20200419203253574.png)]

接"xxx",const char*接 (也可string()初始化,string接;若new string初始化,string *接,需记得再delete err;)
//类直接Beauty()初始化,Beauty&接; (若new Beauty则指针接,记得释放)


三个函数的区别:

![在这里插入图片描述](https://img-blog.csdnimg.cn/202004192052062.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2FpbnU0MTI=,size_16,color_FFFFFF,t_70)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值