04.Eclipse下Ndk开发(以文件拆分合并为例模拟一下开发过程,参考文件加密的过程)

简介: (创建于2017/12/6)1.工具类PatchUtilspackage com.ren.ndk_file_patch;public class PatchUtils { static{ System.

(创建于2017/12/6)

1.工具类PatchUtils

package com.ren.ndk_file_patch;

public class PatchUtils {
    
    static{
        System.loadLibrary("ndk_file_patch");
    }

    public native static void diff(String path,String path_pattern,int count);
    
    public native static void patch(String path_pattern,String merge_path,int count);
}

2.生成的头文件 com_ren_ndk_file_patch_PatchUtils.h

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_ren_ndk_file_patch_PatchUtils */

#ifndef _Included_com_ren_ndk_file_patch_PatchUtils
#define _Included_com_ren_ndk_file_patch_PatchUtils
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_ren_ndk_file_patch_PatchUtils
 * Method:    diff
 * Signature: (Ljava/lang/String;Ljava/lang/String;I)V
 */
JNIEXPORT void JNICALL Java_com_ren_ndk_1file_1patch_PatchUtils_diff
  (JNIEnv *, jclass, jstring, jstring, jint);

/*
 * Class:     com_ren_ndk_file_patch_PatchUtils
 * Method:    patch
 * Signature: (Ljava/lang/String;Ljava/lang/String;I)V
 */
JNIEXPORT void JNICALL Java_com_ren_ndk_1file_1patch_PatchUtils_patch
  (JNIEnv *, jclass, jstring, jstring, jint);

#ifdef __cplusplus
}
#endif
#endif

3.编写的c文件 ndk_file_patch.c

#include "com_ren_ndk_file_patch_PatchUtils.h"
#include <jni.h>
#include <stdio.h>
#include <stdlib.h>
#include<android/log.h>

#define LOGI(FORMAT,...) __android_log_print(ANDROID_LOG_INFO,"renzhenming",FORMAT,__VA_ARGS__);
#define LOGE(FORMAT,...) __android_log_print(ANDROID_LOG_ERROR),"renzhenming",FORMAT,__VA_ARGS__);

long get_file_size(const char *path){
    FILE *fl = fopen(path,"rb");
    //把与fp有关的文件位置指针放到一个指定位置。
    //文件指针定位到文件末尾,偏移0个字节 
    fseek(fl,0,SEEK_END);
    //函数用来获取文件读写指针的当前位置,对于二进制文件,则返回从文件开头到结尾的字节数。
    return ftell(fl);
}

JNIEXPORT void JNICALL Java_com_ren_ndk_1file_1patch_PatchUtils_diff
  (JNIEnv *env, jclass jclz, jstring path_jstr, jstring path_pattern_jstr, jint file_num){

    //转换文件路径
    const char *path = (*env)->GetStringUTFChars(env,path_jstr,NULL);
    const char *path_pattern = (*env)->GetStringUTFChars(env,path_pattern_jstr,NULL);

    //得到分割之后的所有文件路径

    //申请一段连续的内存空间(一个数组)保存所有分割的文件地址
    char **patches = malloc(sizeof(char*)*file_num);

    int i = 0;
    for(;i<file_num;i++){
        patches[i]=malloc(sizeof(char)*100);
        //元素赋值
        //需要分割的文件:C://jason/liuyan.png
        //子文件:C://jason/liuyan_%d.png(path_pattern的格式)
        sprintf(patches[i],path_pattern,(i+1));
        LOGI("patch path:%s",patches[i]);
    }
    //不断读取path文件,循环写入file_num个文件中
        //  整除
        //  文件大小:90,分成9个文件,每个文件10
        //  不整除
        //  文件大小:110,分成9个文件,
        //  前(9-1)个文件为(110/(9-1))=13
        //  最后一个文件(110%(9-1))=6

    //获取文件大小
    int file_size = get_file_size(path);
    //打开这个文件
    FILE *fpr = fopen(path,"rb");

    //整除
    if(file_size % file_num == 0){
        //单个文件大小
        int part = file_size/file_num;

        int i =0;
        //逐一写入设置好的子文件路径中
        for(;i<file_num;i++){
            //从子文件路径打开一个FILE
            FILE *fpw = fopen(patches[i],"wb");
            int j = 0;
            for(;j<part;j++){
                //边读边写
                //fgetc函数功能:从流中读取字符,即从fp所指定的文件中取得下一个字符。这里需要注意,在每取完一个字符时fp会自动向下移动一个字节。这样编成时,程序员就不用再对fp                 //控制了。这种功能在许多读写函数中都有体现。
                fputc(fgetc(fpr),fpw);
            }
            fclose(fpw);
        }
    }else{
        //无法整除
        int part = file_size/(file_num-1);
        int 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<file_size%(file_num-1);i++){
            fputc(fgetc(fpr),fpw);
        }
        fclose(fpw);
    }

    //释放
    i = 0;
    for(;i<file_num;i++){
        free(patches[i]);
    }
    free(patches);

    (*env)->ReleaseStringUTFChars(env,path_jstr,path);
    (*env)->ReleaseStringUTFChars(env,path_pattern_jstr,path_pattern);
}

/*
 * Class:     com_ren_ndk_file_patch_PatchUtils
 * Method:    patch
 * Signature: (Ljava/lang/String;Ljava/lang/String;I)V
 */
JNIEXPORT void JNICALL Java_com_ren_ndk_1file_1patch_PatchUtils_patch
  (JNIEnv *env, jclass jclz, jstring path_pattern_jstr, jstring merge_path_jstr, jint file_num){
    //字符串转换
    const char *merge_path = (*env)->GetStringUTFChars(env,merge_path_jstr,NULL);
    const char *path_pattern = (*env)->GetStringUTFChars(env,path_pattern_jstr,NULL);
    //得到分割后的子文件路径列表
    char **patches = malloc(sizeof(char*)*file_num);
    int i = 0;
    for(;i<file_num;i++){
        patches[i]=malloc(sizeof(char)*100);
        //元素赋值
        //需要分割的文件:C://jason/liuyan.png
        //子文件:C://jason/liuyan_%d.png
        sprintf(patches[i],path_pattern,i+1);
        LOGI("patch path:%s",patches[i]);
    }
    //打开要merge_path为一个FILE
    FILE *fpw = fopen(merge_path,"wb");
    //把所有分割的文件读取一遍,写入到这个总的文件中
    i = 0;
    for(;i<file_num;i++){
        //得到每个子文件的大小
        int file_size = get_file_size(patches[i]);
        //打开每个子文件路径为一个FILE
        FILE *fpr = fopen(patches[i],"rb");
        int j =0;
        for(;j<file_size;j++){
            fputc(fgetc(fpr),fpw);
        }
        fclose(fpr);
    }
    fclose(fpw);

    //释放内存
    i = 0;
    for(;i<file_num;i++){
        free(patches[i]);
    }
    free(patches);

    (*env)->ReleaseStringUTFChars(env,merge_path_jstr,merge_path);
    (*env)->ReleaseStringUTFChars(env,path_pattern_jstr,path_pattern);
}

4.Android.mk文件

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := ndk_file_patch
LOCAL_SRC_FILES := ndk_file_patch.c
LOCAL_LDLIBS := -llog   //使用了log,需要引入

include $(BUILD_SHARED_LIBRARY)

5.开始拆分合并

public class MainActivity extends Activity {
    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 diff(View view){
        String path = SD_CARD_PATH +File.separatorChar+ "2.mp4";
        String path_pattern = SD_CARD_PATH +File.separatorChar+ "2_%d.mp4";
        PatchUtils.diff(path, path_pattern, 2);
        System.out.println("拆分完成");
    }
    public void patch(View view){
        String merge_path = SD_CARD_PATH +File.separatorChar+ "2_new.mp4";
        String path_pattern = SD_CARD_PATH +File.separatorChar+ "2_%d.mp4";
        PatchUtils.patch(path_pattern, merge_path, 2);
        System.out.println("合并完成");
    }
}

6.注意添加权限,6.0动态申请

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
相关文章
|
9月前
|
数据采集 监控 API
加密货币 Pump 监测刮刀工具开发原理及实现路径
开发Pump监测刮刀工具需综合运用高频数据采集、波动率建模、跨平台对冲三大核心技术,2025年的技术瓶颈已从基础数据获取转向超低延迟执行与合规适配。建议采用模块化开发策略,优先实现核心监控功能,再逐步接入AI决策与链上套利模块。代码示例需根据最新交易所API文档动态调整,并严格遵守所在地监管法规。
|
11月前
|
安全 网络协议 算法
零基础IM开发入门(五):什么是IM系统的端到端加密?
本篇将通俗易懂地讲解IM系统中的端到端加密原理,为了降低阅读门槛,相关的技术概念会提及但不深入展开。
416 2
|
安全 网络安全 Android开发
安卓与iOS开发:选择的艺术网络安全与信息安全:漏洞、加密与意识的交织
【8月更文挑战第20天】在数字时代,安卓和iOS两大平台如同两座巍峨的山峰,分别占据着移动互联网的半壁江山。它们各自拥有独特的魅力和优势,吸引着无数开发者投身其中。本文将探讨这两个平台的特点、优势以及它们在移动应用开发中的地位,帮助读者更好地理解这两个平台的差异,并为那些正在面临选择的开发者提供一些启示。
228 56
|
NoSQL 编译器 C语言
C语言调试是开发中的重要技能,涵盖基本技巧如打印输出、断点调试和单步执行,以及使用GCC、GDB、Visual Studio和Eclipse CDT等工具。
C语言调试是开发中的重要技能,涵盖基本技巧如打印输出、断点调试和单步执行,以及使用GCC、GDB、Visual Studio和Eclipse CDT等工具。高级技巧包括内存检查、性能分析和符号调试。通过实践案例学习如何有效定位和解决问题,同时注意保持耐心、合理利用工具、记录过程并避免过度调试,以提高编程能力和开发效率。
491 1
|
XML Android开发 数据格式
Eclipse 创建 XML 文件
Eclipse 创建 XML 文件
229 2
|
NoSQL Java Redis
shiro学习四:使用springboot整合shiro,正常的企业级后端开发shiro认证鉴权流程。使用redis做token的过滤。md5做密码的加密。
这篇文章介绍了如何使用Spring Boot整合Apache Shiro框架进行后端开发,包括认证和授权流程,并使用Redis存储Token以及MD5加密用户密码。
397 0
shiro学习四:使用springboot整合shiro,正常的企业级后端开发shiro认证鉴权流程。使用redis做token的过滤。md5做密码的加密。
|
存储 安全 网络安全
网络安全与信息安全:构建安全防线的多维策略在当今数字化时代,网络安全已成为维护个人隐私、企业机密和国家安全的关键要素。本文旨在探讨网络安全漏洞的本质、加密技术的重要性以及提升公众安全意识的必要性,以期为构建更加坚固的网络环境提供参考。
本文聚焦于网络安全领域的核心议题,包括网络安全漏洞的现状与应对、加密技术的发展与应用,以及安全意识的培养与实践。通过分析真实案例,揭示网络安全威胁的多样性与复杂性,强调综合防护策略的重要性。不同于传统摘要,本文将直接深入核心内容,以简洁明了的方式概述各章节要点,旨在迅速吸引读者兴趣,引导其进一步探索全文。
|
JavaScript 前端开发 安全
安全开发-JS应用&原生开发&JQuery库&Ajax技术&加密编码库&断点调试&逆向分析&元素属性操作
安全开发-JS应用&原生开发&JQuery库&Ajax技术&加密编码库&断点调试&逆向分析&元素属性操作
208 5
|
安全 网络安全 数据安全/隐私保护
网络安全与信息安全:关于网络安全漏洞、加密技术、安全意识等方面的知识分享安卓与iOS开发中的线程管理比较
【8月更文挑战第30天】本文将探讨网络安全与信息安全的重要性,并分享关于网络安全漏洞、加密技术和安全意识的知识。我们将了解常见的网络攻击类型和防御策略,以及如何通过加密技术和提高安全意识来保护个人和组织的信息安全。
|
安全 网络安全 量子技术
网络安全与信息安全:漏洞、加密技术与安全意识的探索安卓应用开发中的内存管理策略
【5月更文挑战第31天】随着互联网的普及,网络安全问题日益严重。本文将深入探讨网络安全漏洞、加密技术以及安全意识等方面的问题,以期提高公众对网络安全的认识和防范能力。

推荐镜像

更多