前言:关于文件的操作你可以使用java的io流可以对文件进行各种操作,这里我们就用到C来操作文件的复制、创建,通过JNI来实现文件的拆分与合并!如果你对C语言的IO使用不是很熟悉的话,请移步《C语言快速讲解(六)联合体、枚举、IO》!
---------分割线--------
展示效果:
---------分割线--------
java代码:MainActivity.java:
package com.fly.demo2;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import java.io.File;
public class MainActivity extends AppCompatActivity {
private FileUtils fileUtils;
private File splitfile;
private File outfile;
private File outmergefile;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fileUtils = new FileUtils();
//要分割的文件地址
splitfile = new File(Environment.getExternalStorageDirectory(), "img.jpg");
outfile = new File(Environment.getExternalStorageDirectory(), "img%d.jpg");
outmergefile = new File(Environment.getExternalStorageDirectory(), "imgcorpy.jpg");
}
public void click1(View view) {
new Thread(new Runnable() {
@Override
public void run() {
fileUtils.split(splitfile.getAbsolutePath(), 2, outfile.getAbsolutePath());
}
}).start();
}
public void click2(View view) {
new Thread(new Runnable() {
@Override
public void run() {
fileUtils.merge(outfile.getAbsolutePath(), 2, outmergefile.getAbsolutePath());
}
}).start();
}
}
FileUtils.java:
package com.fly.demo2;
/**
* Created by Fly on 2017/7/5.
*/
public class FileUtils {
// 加载动态库
static {
System.loadLibrary("native-lib");
}
/**
* 分割文件
* @param splitFilePath 要分割的路径
* @param outPath 输出分割路径 其中每个文件末尾用%d代替 如 D:XXX%d.jpg
* @param number 分割数量
*/
public native void split(String splitFilePath,int number,String outPath);
/**
* 合并被分割的文件
* @param splitFilePath 被分割的文件路径 且有占位符 %d 如 D:XXX%d.jpg
* @param number 被分割的文件数目
* @param outPath 输出路径
*/
public native void merge(String splitFilePath,int number,String outPath);
}
C代码:
//
// Created by Fly on 2017/7/5.
//
#include <jni.h>
#include <stdlib.h>
#include <stdio.h>
#include<android/log.h>
#define LOGE(FORMAT, ...) __android_log_print(ANDROID_LOG_ERROR,"FLY", FORMAT, __VA_ARGS__)
long file_Size(char *path) {
FILE *filep = fopen(path, "rb");
fseek(filep, 0, SEEK_END);
return ftell(filep);
}
/*
* Class: com_fly_demo2_FileUtils
* Method: split_file
* Signature: (Ljava/lang/String;ILjava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_com_fly_demo2_FileUtils_split
(JNIEnv *env, jobject job, jstring splitFilePath, jint number, jstring outPath) {
//分隔文件的路径
char *splitFilePathChar = (*env)->GetStringUTFChars(env, splitFilePath, NULL);
//占位符路径 如 d:xxx%d.jpg
char *outPathChar = (*env)->GetStringUTFChars(env, outPath, NULL);
//输出分割文件的数组指针
FILE **fileArrayP = calloc(number, sizeof(FILE *));
//分割数据FILE
FILE *splitFile = fopen(splitFilePathChar, "rb");
//文件大小
long fileSize = file_Size(splitFilePathChar);
//每个每个文件大小
long file_black_size[number];
LOGE("文件总大小:%ld", fileSize);
//初始化循环变量
int var = 0;
//每个分割文件大小
long blackSize = fileSize / number;
//循环遍历赋值每个文件
for (; var < number; ++var) {
//每一个输出文件的地址
char *outEachPath = calloc(200, sizeof(char));
//格式化文件输出路径
sprintf(outEachPath, outPathChar, var);
//每个文件指向
fileArrayP[var] = fopen(outEachPath, "wb");
//释放
free(outEachPath);
//最后一个
if (var == number - 1) {
//最后一个文件的大小 防止不能被整除
file_black_size[number - 1] = blackSize + fileSize % number;
} else {
//每个文件的文件大小 注意如果文件大小不能被number整数那么最后一个文件大小需要重新计算赋值
file_black_size[var] = blackSize;
}
}
//从文件中读取的byte
int ch;
long current = 0;//当前进度
//所有分割数
for (var = 0; var < number; ++var) {
//最后一块
if (var == number - 1) {
while ((ch = fgetc(splitFile)) != EOF) {
fputc(ch, fileArrayP[var]);
}
} else {
while (current < blackSize) {
ch = fgetc(splitFile);
current++;
fputc(ch, fileArrayP[var]);
}
}
fclose(fileArrayP[var]);
//充值下标
current = 0;
}
free(fileArrayP);
//释放指向
(*env)->ReleaseStringUTFChars(env, splitFilePath, splitFilePathChar);
(*env)->ReleaseStringUTFChars(env, outPath, outPathChar);
}
/*
* Class: com_fly_demo2_FileUtils
* Method: merge_file
* Signature: (Ljava/lang/String;ILjava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_com_fly_demo2_FileUtils_merge
(JNIEnv *env, jobject job, jstring splitFilePath, jint count, jstring outFilePath) {
//占位符路径 如 d:xxx%d.jpg
char *splitFilePathChar = (*env)->GetStringUTFChars(env, splitFilePath, NULL);
//合并文件路徑
char *outFilePathChar = (*env)->GetStringUTFChars(env, outFilePath, NULL);
int var;
//打开输出文件
FILE *outFilep = fopen(outFilePathChar, "wb");
for (var = 0; var < count; ++var) {
//分割文件路径名
char *splitFilePathEeatChar = calloc(200, sizeof(char));
//格式化路径
sprintf(splitFilePathEeatChar, splitFilePathChar, var);
//打开被分割的文件
FILE *filep = fopen(splitFilePathEeatChar, "rb");
int ch;
while ((ch = fgetc(filep)) != EOF) {
fputc(ch, outFilep);
}
free(filep);
fclose(filep);
}
//关闭输出文件指向
fclose(outFilep);
//释放指向
(*env)->ReleaseStringUTFChars(env, splitFilePath, splitFilePathChar);
//释放指向
(*env)->ReleaseStringUTFChars(env, outFilePath, outFilePathChar);
}
--------完-------