java方法

/**
     * 文件分割方法
     *
     * @param srcFilePath 源文件Path
     * @param dstFilePath 分割文件的目标目录
     * @param count       分割个数
     */
    public static void splitFile(String srcFilePath, String dstFilePath, int count) {
        RandomAccessFile raf = null;
        try {
            //获取目标文件 预分配文件所占的空间 在磁盘中创建一个指定大小的文件   r 是只读
            raf = new RandomAccessFile(new File(srcFilePath), "r");
            long length = raf.length();//文件的总长度
            long maxSize = length / count;//文件切片后的长度
            long offSet = 0L;//初始化偏移量
            for (int i = 0; i < count - 1; i++) { //最后一片单独处理
                long begin = offSet;
                long end = (i + 1) * maxSize;
//                offSet = writeFile(file, begin, end, i);
                offSet = getWrite(srcFilePath, dstFilePath, i, begin, end);
            }
            if (length - offSet > 0) {
                getWrite(srcFilePath, dstFilePath, count - 1, offSet, length);
            }
        } catch (FileNotFoundException e) {
            Log.e("TAG", "没有找到文件 srcFilePath:" + srcFilePath);
            e.printStackTrace();
        } catch (IOException e) {
            Log.e("TAG", "IOException");
            e.printStackTrace();
        } finally {
            try {
                if (raf != null)
                    raf.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 指定文件每一份的边界,写入不同文件中
     *
     * @param srcFilePath 源文件
     * @param dstFilePath 目标目录
     * @param index       源文件的顺序标识
     * @param begin       开始指针的位置
     * @param end         结束指针的位置
     * @return long
     */
    public static long getWrite(String srcFilePath, String dstFilePath, int index, long begin,
                                long end) {
        File srcFile = new File(srcFilePath);
        long endPointer = 0L;
        try {
            //申明文件切割后的文件磁盘
            RandomAccessFile in = new RandomAccessFile(new File(srcFilePath), "r");
            //定义一个可读,可写的文件并且后缀名为.tmp的二进制文件
            RandomAccessFile out = new RandomAccessFile(new File(dstFilePath + srcFile.getName()
                    .split("\\.")[0]
                    + "_" + index + ".tmp"), "rw");

            //申明具体每一文件的字节数组
            byte[] b = new byte[1024];
            int n = 0;
            //从指定位置读取文件字节流
            in.seek(begin);
            //判断文件流读取的边界
            while (in.getFilePointer() <= end && (n = in.read(b)) != -1) {
                //从指定每一份文件的范围,写入不同的文件
                out.write(b, 0, n);
            }
            //定义当前读取文件的指针
            endPointer = in.getFilePointer();
            //关闭输入流
            in.close();
            //关闭输出流
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
            Log.e("TAG", "getWrite Exception");
        }
        return endPointer;
    }

    /**
     * @param srcFile 分割文件目录
     * @param dstFile 目标合并文件绝对路径
     */
    public static void merge(String srcFile, String dstFile) {
        File file = new File(srcFile);
        if (file != null && file.exists() && file.listFiles().length > 0) {
            merge(dstFile, srcFile, file.listFiles().length);
        }
    }

    /**
     * 文件合并
     *
     * @param dstFile   指定合并文件
     * @param tempFile  分割前的目录
     * @param tempCount 文件个数
     */
    private static void merge(String dstFile, String tempFile, int tempCount) {
        RandomAccessFile raf = null;
        try {
            //申明随机读取文件RandomAccessFile
            raf = new RandomAccessFile(new File(dstFile), "rw");
            //开始合并文件,对应切片的二进制文件
            File splitFileDir = new File(tempFile);
            File[] files = splitFileDir.listFiles();
            for (int i = 0; i < tempCount; i++) {
                //读取切片文件
                RandomAccessFile reader = new RandomAccessFile(files[i], "r");
                byte[] b = new byte[1024];
                int n = 0;
                //先读后写
                while ((n = reader.read(b)) != -1) {//读
                    raf.write(b, 0, n);//写
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            Log.e("TAG", "merge Exception" + e.getMessage());
        } finally {
            try {
                if (raf != null)
                    raf.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

 

jni 方法

#include <jni.h>
#include <string>
#include<android/log.h>
#include <malloc.h>

#define TAG "TAG"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAG ,__VA_ARGS__) // 定义LOGI类型

//获取文件size大小
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;
}

//srcFilePath_      需要分割的文件
//dstFilePath_      分割的目标目录
//file_num          分割的个数
extern "C"
JNIEXPORT void JNICALL
Java_com_vivo_splitandmarginproject_SplitUtil_splitFile(JNIEnv *env, jclass type,
                                                        jstring srcFilePath_, jstring dstFilePath_,
                                                        jint file_num) {
    //1,首先需要拆分文件的地址,生成拆分后子文件的地址,子文件(可以使用原文件名_%d命名,然后在代码中进行替换,如果嫌麻烦也可以直接用传入多个地址是一样的)。
    //2,需要知道拆分的子文件个数
    const char *srcFilePath = env->GetStringUTFChars(srcFilePath_, NULL);
    const char *dstFilePath = env->GetStringUTFChars(dstFilePath_, NULL);

    LOGI("JNI native diff begin");
    //申请存放多个文件的内存  二级指针首地址
    char **patches = (char **) malloc(sizeof(char *) * file_num);

    for (int i = 0; i < file_num; i++) {
        patches[i] = (char *) malloc(sizeof(char) * 100);
        //对每个地址进行拼接
        sprintf(patches[i], dstFilePath, i);
        LOGI("patch path : %s", patches[i]);
    }

    //  3,源文件的大小,以及是否能整除子文件个数(这里分两种情况处理) 读取源文件大小  根据大小进行拆分
    int fileSize = get_file_size(srcFilePath);
    LOGI("fileSize : %d", fileSize);
    //    打开源文件
    FILE *rfp = fopen(srcFilePath, "rb");
    //   4,读取源文件,循环写入子文件。(这里拆分需要一个个char读取和写入,不然会出问题) 源文件是否正好整除所划分的文件个数  分别处理
    if (fileSize % file_num == 0) {
        int part = fileSize / file_num;
        for (int i = 0; i < file_num; i++) {
            FILE *fwp = fopen(patches[i], "wb");//只写打开或新建一个二进制文件;只允许写数据
            for (int j = 0; j < part; j++) {
                fputc(fgetc(rfp), fwp);
            }
            fclose(fwp);
        }
    } else {
        int part = fileSize / (file_num - 1);
        for (int i = 0; i < file_num - 1; i++) {
            FILE *fwp = fopen(patches[i], "wb");
            for (int j = 0; j < part; j++) {
                fputc(fgetc(rfp), fwp);
            }
            fclose(fwp);
        }
        FILE *fwp = fopen(patches[file_num - 1], "wb");
        for (int i = 0; i < fileSize % (file_num - 1); i++) {
            fputc(fgetc(rfp), fwp);
        }
        fclose(fwp);
    }
    //  5,关闭文件流,释放资源
    fclose(rfp);
    for (int i = 0; i < file_num; i++) {
        free(patches[i]);
    }
    free(patches);

    env->ReleaseStringUTFChars(srcFilePath_, srcFilePath);
    env->ReleaseStringUTFChars(dstFilePath_, dstFilePath);
}

//srcFilePath_      要合并成的文件
//dstFilePath_      分割的目标目录
//file_num          分割的个数
extern "C"
JNIEXPORT void JNICALL
Java_com_vivo_splitandmarginproject_SplitUtil_mergeFile(JNIEnv *env, jclass type,
                                                        jstring srcFilePath_, jstring dstFilePath_,
                                                        jint fileNum) {
    const char *srcFilePath = env->GetStringUTFChars(srcFilePath_, 0);
    const char *dstFilePath = env->GetStringUTFChars(dstFilePath_, 0);

    char **patches = (char **) malloc(sizeof(char *) * fileNum);
    for (int i = 0; i < fileNum; i++) {
        patches[i] = (char *) malloc(sizeof(char) * 100);
        sprintf(patches[i], dstFilePath, i);
        LOGI("patches[i]:%s", patches[i]);
    }

    FILE *fwp = fopen(srcFilePath, "wb");

    for (int i = 0; i < fileNum; i++) {
        int fileSize = get_file_size(patches[i]);
        FILE *frp = fopen(patches[i], "rb");
        LOGI("fileSize:%d", fileSize);
        for (int j = 0; j < fileSize; j++) {
            fputc(fgetc(frp), fwp);
        }
        fclose(frp);
    }
    fclose(fwp);

    for (int i = 0; i < fileNum; i++) {
        free(patches[i]);
    }
    free(patches);

    env->ReleaseStringUTFChars(srcFilePath_, srcFilePath);
    env->ReleaseStringUTFChars(dstFilePath_, dstFilePath);
}