安卓NDK开发案列三:文件的拆分与合并

前言:关于文件的操作你可以使用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);
}
--------完-------

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

等待着冬天的风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值