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;}
阅读全文
1 0
- JNI开发基础系列--文件切割和文件合并
- 文件切割和文件合并
- 文件切割器和文件合并器
- IO综合练习--文件切割和文件合并
- Java实现的文件切割器和文件合并器代码
- ios助手开发系列(六):文件操作系列3 - 文件上传和文件下载
- Java基础----文件的切割合并
- JNI开发基础系列--JNI一些基本概念
- JNI开发基础系列--开启JNI线程
- 文件切割/合并工具
- 如何切割 合并文件
- 切割合并大文件
- 文件切割与合并
- 文件切割与合并
- java切割合并文件
- java基础—文件的切割与合并
- java基础—文件的切割与合并
- 文件和文件组
- fork和exec的区别
- web如何全局捕获ajax异常并且显示到客户端页面
- HDU
- ugui 缩放图片使图片的四个角和四边保持原样
- 卖票系统
- JNI开发基础系列--文件切割和文件合并
- hdu 6143 Killer Names (组合数,递推)
- bst 计数
- github使用入门
- dubbo--远程调用数据交换层客户端类图
- Git系列1:环境配置
- Redis-入门笔记-15min带你一览redis
- Oracle初期学习笔记总结
- copy member from void * array