发现在好久没有写简书了,乘着这个周未写一下,最近一直带实习生做项目,没有太多时间写,好了废话不多说下面开始文件的拆分:
所谓的文件拆分就是把一个文件拆分成若干个小文件:
首先我们要知道文件的大小,然后根据文件的大小和拆分数量计算每个小文件的大小,获取文件大小的代码如下:
//获取文件大小
long get_file_size(char *path){
FILE *fp = fopen(path,"rb");
fseek(fp,0,SEEK_END);
return ftell(fp);
}
下面就是文件拆分的具体实现:
JNIEXPORT void JNICALL Java_com_example_ndk_1file_NativeUtils_mDiff(JNIEnv *env,
jclass jcls, jstring path_jstr, jstring path_pattern_str, jint file_num) {
//获取分割路径
const char* path = (*env)->GetStringUTFChars(env, path_jstr, NULL);
const char* path_pattern = (*env)->GetStringUTFChars(env, path_pattern_str,
NULL);
//得到文件路径列表
char** patches = malloc(sizeof(char*) * file_num);
int i = 0;
for (; i < file_num; i++) {
patches[i] = malloc(sizeof(char) * 100);
sprintf(patches[i], path_pattern, (i + 1));
LOGI("patch path:%s", patches[i]);
}
/**
* 整除
* 文件大小:100,分成5个,每个文件20
* 不整除
* 文件大小:110,分成9个,每个文件13
* 前(9-1)个文件为(110/(9-1))=13
* 最后一个文件(110%(9-1))=6;
*
*/
int file_size = get_file_size(path);
FILE *fpr = fopen(path, "rb");
if (file_size % file_num == 0) {
//边读边写
int part = file_size / file_num;
i = 0;
//逐一写入不同的分割子文件中
for (; i < file_num; i++) {
FILE *fwp = fopen(patches[i], "wb");
int j = 0;
for (; j < part; j++) {
fputc(fgetc(fpr), fwp);
}
fclose(fwp);
}
}else{
//不能整除
int part = file_size / (file_num - 1);
i = 0;
//逐一写入不同的分割子文件中
for(; i < file_num-1; i++) {
FILE *fpw = fopen(patches[i], "wb");
int j = 0;for (; j < part; j++) {fputc(fgetc(fpr), fpw);
}
fclose(fpw);
}
FILE *fpw = fopen(patches[file_num-1],"wb");
i=0;
for(;iReleaseStringUTFChars(env, path_jstr, path);
(*env)->ReleaseStringUTFChars(env, path_pattern_str, path_pattern);
}
Native方法中需要传入,拆分文件的路径,小文件的命名规则,拆分个数。
文件的拆分已经完成,下面我们就进行文件的合并
文件的合并就是把若干个小文件合成一个可用的文件
首先我们要知道合并的原理,在上面的拆分中们们按照命名规则进行文件的拆分,那么下面就按照排好序的小文件合并,Native需要传入拆分的文件数量,拆分命名规则,和合并后文件存放路径,具体代码如下:
//合并
JNIEXPORT void JNICALL Java_com_example_ndk_1file_NativeUtils_mPatch(
JNIEnv *env, jclass jcls, jstring path_pattern_str, jint file_num,jstring total_str) {
//合并之后的路径
const char *merge_path = (*env)->GetStringUTFChars(env,total_str,NULL);
const char* path_pattern = (*env)->GetStringUTFChars(env, path_pattern_str,
NULL);
//得到文件路径列表
char** patches = malloc(sizeof(char*) * file_num);
int i = 0;
for (; i < file_num; i++) {
patches[i] = malloc(sizeof(char) * 100);
sprintf(patches[i], path_pattern, (i + 1));
LOGI("patch path:%s", patches[i]);
}
//把总文件写到一起
FILE *fwp = fopen(merge_path,"wb");
i=0;
for(;i<file_num;i++){
//每一个文件的大小
int filesize = get_file_size(patches[i]);
FILE *fpr = fopen(patches[i],"rb");
int j=0;
for(;j<filesize;j++){
fputc(fgetc(fpr),fwp);
}
fclose(fpr);
}
fclose(fwp);
}
总结:文件拆分其实有点像我们做下载的时候的断点续传,把文件拆分出来然后又合并回去得到完整的文件,在Android中主要用在增量更新。