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 {//申明随机读取文件RandomAccessFileraf = 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);
}