#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <cstring>
using namespace std;
/*
实现拷贝: 打开文件并写入另外一个文件
如果一个文件很大,那么应该怎么读比较合适
分析:四种读,选择按照字节大小去读(read),按照字节大小去写(write)
进度条:
总大小: xxxMB, 已下载:xxxMB, 进度xx.xx%
*/
void test01()
{
// 打开源文件以二进制模式读取
ifstream ifs(R"(E:\embedded\c\clion\CLion-2021.3.4.exe)", ios::binary);
ifs.seekg(0, ios::end); // 将读取指针定位到文件末尾
long long totalSize = ifs.tellg(); // 获取文件总大小
// 打开目标文件以二进制模式写入,如有内容则追加写入
ofstream ofs(R"(E:\embedded\c\clion\CLion-2021.3.4.bp.exe)", ios::binary | ios::app);
ofs.seekp(0, ios::end); // 将写入指针定位到文件末尾
streamsize lastDownLoadSize = ofs.tellp(); // 获取已下载文件的大小
ifs.seekg(lastDownLoadSize, ios::beg); // 将读取指针定位到已下载文件的末尾位置
char buffer[4096] = {0}; // 定义缓冲区
while (!ifs.eof()) {
ifs.read(buffer, sizeof(buffer)); // 从源文件中读取缓冲区大小的数据
streamsize blockSize = ifs.gcount(); // 获取实际读取的字节数
ofs.write(buffer, blockSize); // 将读取到的数据写入目标文件
ofs.flush(); // 刷新写入流
lastDownLoadSize += blockSize; // 更新已下载文件的大小
double recent = (double) lastDownLoadSize / totalSize * 100; // 计算下载进度百分比
printf("总大小: %.2lfMB, 已下载:%.2lfMB, 进度%.2lf%\n",
(double) totalSize / 1024 / 1024,
(double) lastDownLoadSize / 1024 / 1024,
recent
);
}
ifs.close(); // 关闭源文件
ofs.close(); // 关闭目标文件
}
int main()
{
test01();
return 0;
}
上述代码实现了一个将一个文件拷贝到另外一个文件的功能,并在过程中显示下载进度。具体流程如下:
- 使用
ifstream
打开源文件以二进制模式读取,获取文件总大小。 - 使用
ofstream
打开目标文件以二进制模式写入,如有内容则追加写入,获取已下载文件的大小。 - 将读取指针定位到已下载文件的末尾,开始继续下载。
- 使用循环从源文件中按照指定缓冲区大小读取数据