JNI开发基础系列--文件切割和文件合并

来源:互联网 发布:广州网络114 编辑:程序博客网 时间:2024/05/20 20:55

文件切割和文件合并

文件切割思想:

首先计算出一个文件的大小,根据需要切割的份数计算出每份的大小,假如文件的长度为size,需要分割成n份。那么会有2种情况:

  • 当size能被n整除时,即size%n = 0,每份的大小为:size/n
  • 当size不能被n整除时,那么我们计算的思想是这样的,首先让前面(n-1)份进行均分,每份大小为size/(n-1),剩下的没分割玩的留给最后一份,最后一份的大小即size%(n-1),也即size-size*(n-1)

说了这么多废话,还是有点绕,不是很好理解,举个例子帮助理解一下:
比如文件的长度为101,需要切割成4分,显然101%4 = 1,那么就先均分3份
前面3份每份大小为101/3 =33,余数会在转换是抹掉,最后一份的大小就为2

文件合并就没啥说的了,把之前切割的字文件拼接起来组成一个完整的文件

准备工作,在手机sd卡根目录放一个mp3我这里放了一个cd.mp3,至于动态授权就需要自己去申请,不然会报错。

理解了原理之后直接上代码:

java中定义一个类FileUtils,并声明两个native方法

package com.cool.ndktest2;/** * Created by cool on 2017/8/17. */public class FileUtils {    /**     * 文件切割     * @param path 要切割文件的路径     * @param pattern 文件切割后名字的占位符     * @param num 文件切割的数量     */    public native void diff(String path,String pattern,int num);    /**     * 文件合并     * @param patchPath 合并后的路径     * @param pattern 文件切割后名字的占位符     * @param num 之前切割的数量     */    public native void patch(String patchPath,String pattern,int num);}

java中使用

...省略so库加载代码...private String path = Environment.getExternalStorageDirectory().getPath();//文件分割方法public void diff(View view){        FileUtils fileUtils = new FileUtils();        String mp3Path = path + "/cd.mp3";        String path_pattern = path + "/cd_%d.mp3";        fileUtils.diff(mp3Path,path_pattern,4);    }//文件合并方法 public void patch(View view){        FileUtils fileUtils = new FileUtils();        String mp3Path = path + "/cdpatch.mp3";        String path_pattern = path + "/cd_%d.mp3";        fileUtils.patch(mp3Path,path_pattern,4);    }

文件的分割合并的代码都是在c中实现,接下来把目光转向c中,里面每行的注释都非常的清楚

//// Created by cool on 2017/8/16.//#include "com_cool_ndktest2_MainActivity.h"#include <string.h>#include <android/log.h>#include <assert.h>#include <malloc.h>#define TAG "399"#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG,__VA_ARGS__)# define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0])))//返回文件的大小long getFileLenth(char *filePath){    FILE *fp = fopen(filePath,"rb");    fseek(fp,0L,SEEK_END);    long lenth = ftell(fp);    fclose(fp);    return lenth;}//文件切割JNIEXPORT void JNICALL native_diff        (JNIEnv *env, jclass clazz, jstring jpath, jstring jpattern_path, jint jfile_num){    LOGE("文件开始切割");    const char* path = (*env)->GetStringUTFChars(env,jpath,NULL);    const char* pattern = (*env)->GetStringUTFChars(env,jpattern_path,NULL);    //申请二维数组存放切割后的文件名字    char** patchs = (char**)malloc(sizeof(char*)*jfile_num);    //分配内存    for(int i = 0;i<jfile_num;i++){        patchs[i] = malloc(sizeof(char)*100);        sprintf(patchs[i],pattern,i);        LOGE("每段文件的名字:%s",patchs[i]);    }    //计算文件长度    long length = getFileLenth(path);    LOGE("文件长度:%ld",length);    //以读的权限打开文件流    FILE* fp = fopen(path,"rb");    //文件总长度对要切割的分数取模运算    int size = length%jfile_num;    if(size ==0){//刚好能够被整除        //计算切分的每部分大小        int patchSize = length/jfile_num;        for (int i = 0; i < jfile_num; ++i) {            //打开之前要切割的文件,以写入的方式打开文件            FILE *patch = fopen(patchs[i],"wb");//若文件已经存在 就删除,只运行写            for (int j = 0; j < patchSize; j++) {                char ch = fgetc(fp);                fputc(ch,patch);            }            fclose(patch);        }    } else{//不能被整除        //计算切分的每部分大小        int patchSize = length/(jfile_num-1);        for (int i = 0; i < jfile_num - 1; i++) {        //打开之前要切割的文件,以写入的方式打开文件            FILE *patch = fopen(patchs[i],"wb");//若文件已经存在 就删除,只运行写            for (int j = 0; j < patchSize; j++) {                char ch = fgetc(fp);                fputc(ch,patch);            }            fclose(patch);        }        FILE *patch = fopen(patchs[jfile_num-1],"wb");        for (int i = 0; i < length % (jfile_num-1); i++) {            char ch = fgetc(fp);            fputc(ch,patch);        }        fclose(patch);    }    fclose(fp);    for (int i = 0; i < jfile_num; ++i) {        free(patchs[i]);    }    free(patchs);    patchs =NULL;    LOGE("文件切割完成");    (*env)->ReleaseStringChars(env,jpath,path);    (*env)->ReleaseStringChars(env,jpattern_path,pattern);}//文件合并JNIEXPORT void JNICALL native_patch        (JNIEnv *env, jclass clazz, jstring jpatchPath, jstring jpatternPath, jint jfile_num){    LOGE("文件开始合并");    char *patchPath = (*env)->GetStringUTFChars(env,jpatchPath,NULL);    char *patternPath = (*env)->GetStringUTFChars(env,jpatternPath,NULL);    //申请二维数组存放切割后的文件名字    char** patchs = (char**)malloc(sizeof(char*)*jfile_num);    //分配内存    for(int i = 0;i<jfile_num;i++){        patchs[i] = malloc(sizeof(char)*100);        sprintf(patchs[i],patternPath,i);        LOGE("每段文件的名字:%s",patchs[i]);    }    FILE *fp = fopen(patchPath,"wb");    for(int i=0;i<jfile_num;i++){        int patchLength = getFileLenth(patchs[i]);        FILE *patch = fopen(patchs[i],"rb");        for (int j = 0; j < patchLength; j++) {            fputc(fgetc(patch),fp);        }        fclose(patch);    }    fclose(fp);    for (int i = 0; i < jfile_num; ++i) {        free(patchs[i]);    }    free(patchs);    patchs =NULL;    LOGE("文件合并完成");    (*env)->ReleaseStringChars(env,jpatchPath,patchPath);    (*env)->ReleaseStringChars(env,jpatternPath,patternPath);}//动态注册代码static const JNINativeMethod gMethods[] = {        {                "diff","(Ljava/lang/String;Ljava/lang/String;I)V",(void*)native_diff        },        {                "patch","(Ljava/lang/String;Ljava/lang/String;I)V",(void*)native_patch        }};static int registerNatives(JNIEnv* engv){    LOGE("registerNatives begin");    jclass  clazz;    clazz = (*engv) -> FindClass(engv, "com/cool/ndktest2/FileUtils");    if (clazz == NULL) {        LOGE("clazz is null");        return JNI_FALSE;    }    if ((*engv) ->RegisterNatives(engv, clazz, gMethods, NELEM(gMethods)) < 0) {        LOGE("RegisterNatives error");        return JNI_FALSE;    }    return JNI_TRUE;}JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved){    LOGE("jni_OnLoad begin");    JNIEnv* env = NULL;    jint result = -1;    if ((*vm)->GetEnv(vm,(void**) &env, JNI_VERSION_1_4) != JNI_OK) {        LOGE("ERROR: GetEnv failed\n");        return -1;    }    assert(env != NULL);    registerNatives(env);    return JNI_VERSION_1_4;}
原创粉丝点击