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);
}