前言
在上传一些大的文件时候,用到文件的差分,和合并。这里是针对文件的二进制差分和合并,不区分格式
文件拆分
JNIEXPORT void JNICALL native_diff
image.png
(JNIEnv *env, jclass clazz, jstring path, jstring pattern_Path, jint file_num)
{
LOGI("JNI native diff begin");
const char path_Str = (env) -> GetStringUTFChars(env, path, NULL);
const char pattern_Path_str = (env) ->GetStringUTFChars(env, pattern_Path, NULL);
//申请二维字符数据, 存放子文件名
char **patches = (char **)malloc(sizeof(char *) * file_num);
int i =0;
for (; i < file_num; i++) {
//每个文件名申请地址
LOGI("char = %d char * = %d", sizeof(char), sizeof(char ));
patches[i] = (char) malloc(sizeof(char) * 100);
// 需要分割的文件 Vibrato.mp4
// 每个子文件名称 Vibrato_n.mp4
sprintf(patches[i], pattern_Path_str, i);// 格式化文件名
LOGI("patch path : %s",patches[i]);
}
int fileSize = get_file_size(path_Str);
FILE fpr = fopen(path_Str, "rb");
/
* 1.判断文件大小能够被 file_num整除
* 2.能整除就平分
* 3.不能整除就先分 file_num -1
* */
if (fileSize % file_num == 0) {
int part = fileSize / file_num;
for (int i =0; i< file_num; i++) {
FILE *fpw = fopen(patches[i], "wb");//文件已经存在 就删除,只运行写
for (int j =0; j < part; j++) {
fputc(fgetc(fpr), fpw);
}
fclose(fpw);
}
} else {
int part = fileSize / (file_num - 1);
for (int i =0 ; i< file_num - 1; i++) {
FILE fpw = fopen(patches[i], "wb");//文件已经存在 就删除,只运行写
for (int j =0; j < part; j++) {
fputc(fgetc(fpr), fpw);
}
fclose(fpw);
}
FILE fpw = fopen(patches[file_num - 1], "wb");
for (int i = 0; i < fileSize % (file_num - 1); i++) {
fputc(fgetc(fpr),fpw);
}
fclose(fpw);
}
fclose(fpr);
for (int i =0; i< file_num; i++) {
free(patches[i]);
}
free(patches);
(env)->ReleaseStringUTFChars(env, path, path_Str);
(env)->ReleaseStringUTFChars(env, pattern_Path, pattern_Path_str);
}
分析图:
文件合并
JNIEXPORT void JNICALL native_patch
(JNIEnv *env, jclass clazz, jstring merge_path, jstring pattern_Path, jint file_num)
{
LOGI("JNI native patch begin");
const char path_Str = (env) -> GetStringUTFChars(env, merge_path, NULL);
const char pattern_Path_str = (env) ->GetStringUTFChars(env, pattern_Path, NULL);
//申请二维字符数据, 存放子文件名
char **patches = (char **)malloc(sizeof(char *) * file_num);
int i =0;
for (; i < file_num; i++) {
//每个文件名申请地址
// LOGI("char = %d char * = %d", sizeof(char), sizeof(char ));
patches[i] = (char) malloc(sizeof(char) * 100);
// 需要分割的文件 Vibrato.mp4
// 每个子文件名称 Vibrato_n.mp4
sprintf(patches[i], pattern_Path_str, i);// 格式化文件名
}
FILE fpw = fopen(path_Str, "wb");
for (int i =0; i < file_num; i++) {
int filesize = get_file_size(patches[i]);
FILE fpr = fopen(patches[i], "rb");
for (int j =0; j < filesize; j++) {
fputc(fgetc(fpr), fpw);
}
fclose(fpr);
}
fclose(fpw);
for (int i =0; i< file_num; i++) {
free(patches[i]); //每一个malloc 对应一个free
}
free(patches);
(env)->ReleaseStringUTFChars(env, merge_path, path_Str);
(env)->ReleaseStringUTFChars(env, pattern_Path, pattern_Path_str);
}
//获取文件大小
long get_file_size(const char* path) {
FILE *fp = fopen(path, "rb"); //打开一个文件, 文件必须存在,只运行读
fseek(fp, 0, SEEK_END);
long ret = ftell(fp);
fclose(fp);
return ret;
}
.赞助本文及本系列,由老司机学院动脑学院特约赞助。
注意:Android jni目录
网友评论