侧边栏壁纸
  • 累计撰写 14 篇文章
  • 累计创建 1 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

C++ 文件分块

詹迪佳
2024-08-01 / 0 评论 / 0 点赞 / 29 阅读 / 4297 字

头文件

#include<iostream>
#include<vector>
#include<fstream>
using namespace std;

预定义

在文件分块和合并的过程中,可能我们操作的文件大小有数十GB,超过了我们电脑内存的大小,此时我们需要将文件逐步读入缓冲区,然后再进行操作,避免文件大小过大挤爆内存。

constexpr size_t BUFFER_SIZE = 1024 * 1024; // 缓冲区大小 1MB

单线程

文件分块

文件分块流程如下所示

  1. 获取文件大小

  2. 计算每个分块的大小

  3. 对文件进行切分并通过二进制文件输出流输出到目标文件中

  4. 分块结束

void SplitFile(fstream* input, vector<string>&files)
{
	if(files.size() <= 1)
		throw "name.size() <= 1";
	
	//获取文件大小
	size_t size = 0;
	input->seekg(0, ios::end);
	size = input->tellg();
	input->seekg(0, ios::beg);

	//计算分块大小
	size_t part_size = size / files.size();
	size_t last_size = size - part_size * (files.size() - 1);

	char* buffer = new char[BUFFER_SIZE];
	for (size_t i = 0; i < files.size(); i++)
	{
		fstream output(files[i], ios::out | ios::binary);
		size_t cur_size = (i == files.size() - 1) ? last_size : part_size;
		
		if (!output.is_open())
			throw "output file open failed";

		while (cur_size > 0)
		{
			size_t read_size = cur_size > BUFFER_SIZE ? BUFFER_SIZE : cur_size;
			input->read(buffer, read_size);
			output.write(buffer, read_size);
			cur_size -= read_size;
		}
		
		output.close();
	}
	delete[] buffer;
}

文件合并

文件合并流程如下所示

  1. 对于将被合并的文件,通过fstream来获取文件二进制输入流

  2. 将文件逐步读入缓冲区

  3. 将缓冲区的文件输出

  4. 合并结束

void MergeFile(fstream* output, vector<string>files)
{
	char* buffer = new char[BUFFER_SIZE];
	for (size_t i = 0; i < files.size(); i++)
	{
		fstream input(files[i], ios::in | ios::binary);
		if (!input.is_open())
			throw "input file open failed";
		input.seekg(0, ios::end);
		size_t size = input.tellg();
		input.seekg(0, ios::beg);
		while (size > 0)
		{
			size_t read_size = size > BUFFER_SIZE ? BUFFER_SIZE : size;
			input.read(buffer, read_size);
			output->write(buffer, read_size);
			size -= read_size;
		}
		input.close();
	}
	delete[] buffer;
}

测试代码

int main()
{
	fstream file("C:/Users/24761/Desktop/test/input.zip", ios::out | ios::binary | ios::in);
	if (!file.is_open())
		throw "input file open failed";

	//分块文件路径
	vector<string>files = { "C:/Users/24761/Desktop/test/output1.zip","C:/Users/24761/Desktop/test/output2.zip","C:/Users/24761/Desktop/test/output3.zip" };
	
	//分割文件
	SplitFile(&file, files);
	
	//将文件流重置到开头
	file.seekg(0, ios::beg);
	
	//合并文件
	MergeFile(&file, files);
}

0

评论区