04.Eclipse下Ndk開發(以檔案拆分合併為例模擬一下開發過程,參考檔案加密的過程)
(建立於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"/>
相關文章
- Android開發之音訊配置檔案audio_policy.conf解析全過程Android音訊
- 專案開發過程中的管理規範
- vue專案開發過程常見問題Vue
- 簽署Java檔案的要求及過程Java
- SpringBoot配置檔案讀取過程分析Spring Boot
- 檔案系統修復的一個過程
- 你開發過程中,都有用過哪些虛擬機器?虛擬機
- 學習過程中,專案檔案、程式碼疑惑點
- 記一次PMML檔案的處理過程
- 一個 java 檔案的執行過程詳解Java
- java中listFiles(Filefilter filter)檔案過濾器的實現過程JavaFilter過濾器
- Spark-Shuffle過程概要參考Spark
- 深入wepy原始碼:wpy檔案編譯過程原始碼編譯
- 傑裡之Bin 檔案燒錄過程【篇】
- SQL Server資料庫還原過程記錄,bak檔案+mdf檔案SQLServer資料庫
- openGauss 配置檔案參考
- 微信小程式開發 -- 通過雲函式下載任意檔案微信小程式函式
- 如何參與開源專案 - 細說 GitHub 上的 PR 全過程Github
- Sql Server 資料庫中呼叫dll檔案的過程SQLServer資料庫
- 開發環境下PP檔案的建立開發環境
- MDK編譯過程及檔案型別全解編譯型別
- Java使用javacv處理影片檔案過程記錄Java
- 你有開發過chrome外掛嗎?說說你的開發過程Chrome
- Linux下/etc/profile、~/.bash_profile等幾個檔案的執行過程Linux
- iris-go 框架構建登陸 API 專案開發過程Go框架架構API
- 谷歌正在開發安卓平臺增量檔案系統:遊戲支援在下載過程中體驗谷歌安卓遊戲
- Android Apk 檔案反編譯和重新打包的過程分析AndroidAPK編譯
- 使用XBIM過程中出現的“未能載入檔案或程式”
- 突然地心血來潮,為 MaixPy( k210 micropython ) 新增看門狗(WDT) C 模組的開發過程記錄,給後來的人做開發參考。AIPython
- 總結開發過程踩到的坑(一)
- mpvue & 小程式開發過程中的坑Vue
- puppeteer在開發過程中的實踐
- 軟體開發的生命週期過程
- 達夢資料庫資料檔案遷移過程資料庫
- 如何優化產品開發過程?優化
- 支付寶介面對接開發過程
- 開發小程式過程中採坑
- JavaGuns開發基礎框架搭建過程Java框架