一、实现思路
创建native方法,然后生成so库,然后调用即可
二、实现
1、创建native方法
NDKFileUtils.java
public class NDKFileUtils {
static {
System.loadLibrary("native-lib");
}
/**
* 文件的拆分
* @param path 当前文件的地址
* @param path_pattern 需要保存的路径
* @param count 需要拆分的数量
*/
public native static void diff(String path, String path_pattern, int count);
/**
* 文件的合并
* @param merge_path 合并文件的路径
* @param path_pattern 拆分的文件的路径
* @param count 拆分的数量
*/
public native static void patch(String merge_path,String path_pattern, int count);
}
2、调用native方法
MainActivity
public class MainActivity extends AppCompatActivity {
private String sd_card_path;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sd_card_path= Environment.getExternalStorageDirectory().getAbsolutePath();
}
public void chaifen(View view) {
String path = sd_card_path + File.separatorChar + "aaaa.mp4";
String path_pattern = sd_card_path + File.separatorChar + "aaaa_%d.mp4";
try {
NDKFileUtils.diff(path,path_pattern,4);
} catch (Throwable abloe) {
Log.i("wanxiaofan", "error:"+abloe.getMessage());
}
}
public void hebing(View view) {
String path = sd_card_path + File.separatorChar + "aaaa_merge.mp4";
String path_pattern = sd_card_path + File.separatorChar + "aaaa_%d.mp4";
NDKFileUtils.patch(path,path_pattern,4);
}
}
3、使用javah生成头文件
com_xiaofan_testndk2_NDKFileUtils.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_xiaofan_testndk2_NDKFileUtils */
#ifndef _Included_com_xiaofan_testndk2_NDKFileUtils
#define _Included_com_xiaofan_testndk2_NDKFileUtils
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_xiaofan_testndk2_NDKFileUtils
* Method: diff
* Signature: (Ljava/lang/String;Ljava/lang/String;I)V
*/
JNIEXPORT void JNICALL Java_com_xiaofan_testndk2_NDKFileUtils_diff
(JNIEnv *, jclass, jstring, jstring, jint);
/*
* Class: com_xiaofan_testndk2_NDKFileUtils
* Method: patch
* Signature: (Ljava/lang/String;Ljava/lang/String;I)V
*/
JNIEXPORT void JNICALL Java_com_xiaofan_testndk2_NDKFileUtils_patch
(JNIEnv *, jclass, jstring, jstring, jint);
#ifdef __cplusplus
}
#endif
#endif
4、c文件实现头文件中的方法
native-lib.c
#include <jni.h>
#include "com_xiaofan_testndk2_NDKFileUtils.h"
#include <stdlib.h>
#include <stdio.h>
#include <android/log.h>
#define LOGI(FORMAT, ...) __android_log_print(ANDROID_LOG_INFO,"wanxiaofan",FORMAT,__VA_ARGS__);
#define LOGE(FORMAT, ...) __android_log_print(ANDROID_LOG_ERROR,"wanxiaofan",FORMAT,__VA_ARGS__);
//获取文件大小
long get_file_size(char *path) {
FILE *fp = fopen(path, "rb");
if (fp == NULL) {
return 0;
} else {
fseek(fp, 0, SEEK_END);
return ftell(fp);
}
}
JNIEXPORT void JNICALL Java_com_xiaofan_testndk2_NDKFileUtils_diff
(JNIEnv *env, jclass jcls, jstring path_jstr, jstring path_pattern_jstr, jint file_num) {
//jstring->char*
const char *path = (*env)->GetStringUTFChars(env, path_jstr, JNI_FALSE);
const char *path_pattern = (*env)->GetStringUTFChars(env, path_pattern_jstr, JNI_FALSE);
//得到分割之后的子文件的路径列表
char **patches = malloc(sizeof(char *) * file_num);
int i = 0;
for (; i < file_num; i++) {
patches[i] = malloc(sizeof(char) * 100);
//元素赋值
//D:aaa.mp4 ---> D:aaa_%d.mp4
sprintf(patches[i], path_pattern, (i + 1));
LOGI("patch path:%s", patches[i]);
}
//不断读取path文件,循环写入file_num个文件中
int fileSize = get_file_size(path);
LOGI("fileSize:%d", fileSize);
FILE *fpr = fopen(path, "rb");
if (fileSize != 0 && fpr != NULL) {
if (fileSize % file_num == 0) {
//能整除
//单个文件大小
int part = fileSize / file_num;
i = 0;
//逐一写入不同的分割子文件中
for (; i < file_num; i++) {
FILE *fpw = fopen(patches[i], "wb");
int j = 0;
for (; j < part; j++) {
//边读边写
fputc(fgetc(fpr), fpw);
}
fclose(fpw);
}
} else {
//不整除
int part = fileSize / (file_num - 1);
i = 0;
//逐一写入不同的分割子文件中
for (; i < file_num - 1; i++) {
FILE *fpw = fopen(patches[i], "wb");
int j = 0;
for (; j < part; j++) {
//边读边写
fputc(fgetc(fpr), fpw);
}
fclose(fpw);
}
//最后一个
FILE *fpw = fopen(patches[file_num - 1], "wb");
i = 0;
for (; i < (fileSize % (file_num - 1)); i++) {
fputc(fgetc(fpr), fpw);
}
fclose(fpw);
}
}
//关闭被分割的文件
fclose(fpr);
//释放
i = 0;
for (; i < file_num; i++) {
free(patches[i]);
}
free(patches);
(*env)->ReleaseStringChars(env, path_jstr, path);
(*env)->ReleaseStringChars(env, path_pattern_jstr, path_pattern);
}
JNIEXPORT void JNICALL Java_com_xiaofan_testndk2_NDKFileUtils_patch
(JNIEnv * env, jclass jcls, jstring path_jstr, jstring path_pattern_jstr, jint count) {
//合并之后的文件
const char *merge_path = (*env)->GetStringUTFChars(env, path_jstr, JNI_FALSE);
//被分割子文件的路径
const char *pattern_path = (*env)->GetStringUTFChars(env, path_pattern_jstr, JNI_FALSE);
//得到分割之后的子文件的路径列表
char **patches = malloc(sizeof(char *) * count);
int i = 0;
for (; i < count; i++) {
patches[i] = malloc(sizeof(char) * 100);
//元素赋值
//D:aaa.mp4 ---> D:aaa_%d.mp4
sprintf(patches[i], pattern_path, (i + 1));
LOGI("patch path:%s", patches[i]);
}
//把所有的分割文件读取一遍,写入一个总文件中
i=0;
FILE *fpw=fopen(merge_path,"wb");
for (;i<count;i++){
//每个子文件的大小
int fileSize=get_file_size(patches[i]);
FILE *fpr=fopen(patches[i],"rb");
int j=0;
for (; j <fileSize ; j++) {
fputc(fgetc(fpr),fpw);
}
fclose(fpr);
}
fclose(fpw);
//释放
i = 0;
for (; i < count; i++) {
free(patches[i]);
}
free(patches);
(*env)->ReleaseStringChars(env, path_jstr, merge_path);
(*env)->ReleaseStringChars(env, path_pattern_jstr, pattern_path);
}
三、注意
不知道为什么在三星J5的手机获取不到文件的大小,也没有找到原因