分割与合并的思想
1. 分割:和安卓多线程下载类似 ,首先将文件长度按N段分,然后将每段文件读取并写入到相应的临时文件,以达到分割的目的
2. 合并:将每段临时文件依次读取,然后写入到要合并成的新文件
注意细节
1. 文件打开后记得要关闭
2. 对文件打开的状态进行判断,处理异常
3. fgets函数会获取行尾的\n,必要时进行相关处理,fputs输入字符串时不会自动添加\n
4. 对最后一块的长度进行特殊处理,因为它不一定等于每一块的长度
5. 对操作的分割合并的文件使用二进制的模式进行打开
6. 注意feof函数的使用,在文件指针指向EOF时,下一次读取feof才会返回1
源代码
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
int main(){
char file_path[] = "D:\\a.txt";
FILE *file = fopen(file_path,"w");
char content[] = "I Have a Dream";
fputs(content,file);
fclose(file);
getchar();
return 0;
}
*/
/*
int main(){
struct Student{
char name[10];
int num;
int age;
char addr[30];
} stud[10];
char file_path[] = "D:\\stud.dat";
FILE * output = fopen(file_path,"w");
if(output == NULL){
printf("无法打开文件");
exit(0);
}
for(int i=0;i<10;i++)
scanf("%s %d %d %s",stud[i].name,&stud[i].num,&stud[i].age,stud[i].addr);
fwrite(&stud[i],sizeof(struct Student),1,output);
}
flose(output);
getchar();
return 0;
}
*/
//获取文件大小
int getFileSize(char old_file_path[])
{
FILE *file = fopen(old_file_path, "r");
fseek(file, 0, SEEK_END);
long fileSize = ftell(file);
return fileSize;
}
/*
int main(){
//分为两步
//第一步:获取分割文件名称
//源文件
char source_file_path[] = "D:\\timg.gif";
int file_number = 6;
//开辟一块内存区域:用于存储文件的名称(二维指针)
//存放字符串(二维字符指针)
//首先:char *p = source_file_path;--首地址(字符串)
//char source_file_path[] = "/Users/yangshaohong/Desktop/icon_image_1.gif";
//char source_file_path[] = "/Users/yangshaohong/Desktop/icon_image_2.gif";
//char source_file_path[] = "/Users/yangshaohong/Desktop/icon_image_3.gif";
char **file_name_array = (char**)malloc(sizeof(char*)*file_number);
for(int i = 0 ; i < file_number ; i++){
//开辟内存空间,用于存放文件路径
file_name_array[i] = (char*)malloc(sizeof(char)*300);
//赋值(字符串的格式化:sprintf)
//结果:/Users/yangshaohong/Desktop/icon_image_0.gif
//结果:/Users/yangshaohong/Desktop/icon_image_1.gif
sprintf(file_name_array[i],"D:\\timg_%d.gif",i);
printf("文件名称:%s\n",file_name_array[i]);
}
//第二步:向指定的分割文件写入内容
//分析问题:每一个文件大小是多少?
//假设:源文件大小51 分割成6个文件 每一个文件的大小?
//两种情况:第一种情况能够平分(54%6=0)
//第二种情况不能够平分(50%6!=0)
//例如:源文件大小51 分割成6个文件 前5个10 最后1个1
//例如:源文件大小51 分割成7个文件 前6in?51/(7-1)=8 最后1个51%(7-1)=3
//例如:源文件大小51 分割成8个文件 前7个51/(8-1)=7 最后1个51%(8-1)=2
//例如:源文件大小51 分割成11个文件 前10个51/(11-1)=5 最后1个51%(11-1)=1
//以此类推: 源文件大小num 分割成n个 前n-1个大小=num/(n-1) 最后1个大小=num%(n-1)
long file_size_sum = getFileSize(source_file_path);
//打开源文件
FILE *source_p = fopen(source_file_path,"rb");
if(file_size_sum%file_number == 0){
//平均分
//计算每一个分割文件大小
long file_size = file_size_sum / file_number;
//遍历:写入内容
//外层循环控制分割文件,内存循环控制文件的写入
for(int i = 0;i<file_number;i++){
//打开分割文件
FILE *file_cut = fopen(file_name_array[i],"wb");
for(int j = 0 ;j<file_size;j++){
//参数一:获取源文件内容
//参数二:写入分割-目标文件
fputc(fgetc(source_p),file_cut);
}
//关闭当前分割文件流
fclose(file_cut);
}
//关闭源文件流
fclose(source_p);
}else{
//不均等
//计算每一个分割文件大小
long file_size = file_size_sum / (file_number-1);
//处理前面的分割文件
//遍历:写入内容
//外层循环控制分割文件,内存循环控制文件的写入
for(int i = 0;i<file_number-1;i++){
//打开分割文件
FILE *file_cut = fopen(file_name_array[i],"wb");
for(int j = 0 ;j<file_size;j++){
//参数一:获取源文件内容
//参数二:写入分割-目标文件
fputc(fgetc(source_p),file_cut);
}
//关闭当前分割文件流
fclose(file_cut);
}
//写入最后一个文件(单独处理)
//打开分割文件
//打开最后一个文件
FILE *file_last_cut = fopen(file_name_array[file_number - 1],"wb");
long last_file_size = file_size_sum % (file_number-1);
//你不这么做,后面会填写'\0'
for(int j = 0 ;j<last_file_size;j++){
//参数一:获取源文件内容
//参数二:写入分割-目标文件
fputc(fgetc(source_p),file_last_cut);
}
//关闭当前分割文件流
fclose(file_last_cut);
//关闭源文件流
fclose(source_p);
}
getchar();
return 0;
}
*/
//合并文件
int main()
{
//分为两步
//第一步:获取分割文件名称
//源文件
char source_file_path[] = "D:\\timg.gif";
//合并之后的文件路径
char merge_file_path[] = "D:\\timg_marge.gif";
int file_number = 6;
//开辟一块内存区域:用于存储文件的名称(二维指针)
//存放字符串(二维字符指针)
char **file_name_array = (char **)malloc(sizeof(char *) * file_number);
for (int i = 0; i < file_number; i++)
{
//开辟内存空间,用于存放文件路径
file_name_array[i] = (char *)malloc(sizeof(char) * 300);
//赋值(字符串的格式化:sprintf)
sprintf(file_name_array[i], "D:\\timg_%d.gif", i);
printf("文件名称:%s\n", file_name_array[i]);
}
//合并文件
//打开源文件
FILE *merge_p = fopen(merge_file_path, "wb");
for (int i = 0; i < file_number; i++)
{
//计算每一个分割文件的大小
long file_size_sum = getFileSize(file_name_array[i]);
//打开分割文件,重分割的文件中读取内容
FILE *file_cut = fopen(file_name_array[i], "rb");
for (int j = 0; j < file_size_sum; j++)
{
//参数一:分割文件(源文件)
//参数二:写入合并的文件-目标文件
//加密也是一样的,将fgetc(file_cut)按照我们之前的做法进行
fputc(fgetc(file_cut), merge_p);
}
//关闭当前分割文件流
fclose(file_cut);
}
//关闭源文件流
fclose(merge_p);
getchar();
return 0;
}