前言
在上傳一些大的文件時候,用到文件的差分,和合并。這里是針對文件的二進制差分和合并,不區分格式
文件拆分
JNIEXPORT void JNICALL native_diff
(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);
}
分析圖:
image.png
文件合并
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目錄