【轉】文件讀寫NDK(或Linux)

原文網址:http://www.ithao123.cn/content-10709539.htmlhtml

使用NDK進行文件讀寫,有利於保存數據的安全性,項目須要,要文件讀寫從Java中處理搬到Linux平臺,爲了方便兩個平臺的代碼維護一致,使用JNI進行重寫編寫;java

 

public class MainActivity extends Activity implements OnClickListener {

	private String tag = getClass().getSimpleName();
	private TextView textView;
	private static final String filePath = "/mnt/sdcard/hello.txt";
	private int num = 0;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		textView = (TextView) findViewById(R.id.textView);
		findViewById(R.id.bt_add).setOnClickListener(this);
		findViewById(R.id.bt_del).setOnClickListener(this);
		findViewById(R.id.bt_update).setOnClickListener(this);
		findViewById(R.id.bt_select).setOnClickListener(this);
	}

	@Override
	public void onClick(View v) {
		switch (v.getId()) {
		case R.id.bt_add:
			num++;
			JniFileTools.writeFile(filePath, ", "+num);
			textView.setText(JniFileTools.readFile(filePath));
			break;
		case R.id.bt_del:
			JniFileTools.deleteString(filePath, ", "+num);
			textView.setText(JniFileTools.readFile(filePath));
			if(num > 0){
				num--;
			}
			break;
		case R.id.bt_update:
			break;
		case R.id.bt_select:
			textView.setText(JniFileTools.readFile(filePath));
			break;
		default:
			break;
		}
	}
}

JNI接口:android

 

 

package jni.file.tools;

public class JniFileTools {

	private final static String tag = "JniFileTools";

	static {
		System.loadLibrary("opfile");
	}

	public final static native String readFile(String filePath);

	public final static native boolean writeFile(String filePath, String content);

	public final static native boolean deleteString(String filePath,
			String content);

}


實現3個方法:c++

 

Java_jni_file_tools_JniFileTools_readFile();安全

Java_jni_file_tools_JniFileTools_writeFile();ide

Java_jni_file_tools_JniFileTools_deleteString();函數

JniFileTools.cppthis

 

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

void Log_i(const char* log, ...) {
	// 請引入#include <stdarg.h>
	va_list arg;
	va_start(arg, log);
	__android_log_vprint(ANDROID_LOG_INFO, "JniLogTools", log, arg);
	va_end(arg);
}

void readFromFile(char* fileName, char *str) {
	FILE *fp;
	int n = 0;
	char strTemp[128];
	fp = fopen(fileName, "r");
	if (fp == NULL) {
		Log_i("readFromFile打開失敗");
		return;
	}
	while (NULL != fgets(strTemp, sizeof(strTemp), fp)) {
		strcat(str, strTemp);
	}
	fclose(fp);
	return;
}

unsigned char writeToFile(char* fileName, char* content, const char * mode) {
	FILE *fp;
	fp = fopen(fileName, mode); //w+ , "a+"
	if (fp == NULL) {
		fclose(fp);
		return false;
	}
	int length = strlen(content);
	for (int i = 0; i < length; i++) {
		fputc(content[i], fp);
	}
	fclose(fp);
	return true;
}

char * jstringToChar(JNIEnv *env, jstring jstr) {
	char * rtn = NULL;
	jclass clsstring = env->FindClass("java/lang/String");
	jstring strencode = env->NewStringUTF("UTF-8");
	jmethodID mid = env->GetMethodID(clsstring, "getBytes",
			"(Ljava/lang/String;)[B");
	jbyteArray barr = (jbyteArray) env->CallObjectMethod(jstr, mid, strencode);
	jsize alen = env->GetArrayLength(barr);
	jbyte * ba = env->GetByteArrayElements(barr, JNI_FALSE);
	if (alen > 0) {
		rtn = (char*) malloc(alen + 1); //new char[alen+1];
		memcpy(rtn, ba, alen);
		rtn[alen] = 0;
	}
	env->ReleaseByteArrayElements(barr, ba, 0);
	return rtn;
}

jstring charTojstring(JNIEnv* env, const char* pat) {
	jclass strClass = env->FindClass("Ljava/lang/String;");
	jmethodID ctorID = env->GetMethodID(strClass, "<init>",
			"([BLjava/lang/String;)V");
	jbyteArray bytes = env->NewByteArray(strlen(pat));
	env->SetByteArrayRegion(bytes, 0, strlen(pat), (jbyte*) pat);
	jstring encoding = env->NewStringUTF("utf-8");
	return (jstring) env->NewObject(strClass, ctorID, bytes, encoding);
}

char *delSubstr(char *str, char *delstr) {
	char *p, *q;
	char *src, *dst;
	dst = src = str;
	while (*src != '\0') {
		p = src;
		q = delstr;
		while (*p == *q && *q != '\0') {
			p++;
			q++;
		}
		if (*q == '\0') {
			src = p;
		} else {
			*dst++ = *src++;
		}
	}
	*dst = '\0';
	return str;
}

JNIEXPORT jstring JNICALL Java_jni_file_tools_JniFileTools_readFile(
		JNIEnv * env, jclass cls, jstring filePath) {
	char str[1024];
	memset(str, 0, sizeof(str));
	readFromFile(jstringToChar(env, filePath), str);
	return (env)->NewStringUTF(str);
}

JNIEXPORT jboolean JNICALL Java_jni_file_tools_JniFileTools_writeFile(
		JNIEnv * env, jclass cls, jstring filePath, jstring content) {
	writeToFile(jstringToChar(env, filePath), jstringToChar(env, content),
			"a+");
	return true;
}

JNIEXPORT jboolean JNICALL Java_jni_file_tools_JniFileTools_deleteString(
		JNIEnv * env, jclass cls, jstring filePath, jstring content) {
	char str[1024];
	memset(str, 0, sizeof(str));
	readFromFile(jstringToChar(env, filePath), str);
	delSubstr(str,jstringToChar(env, content));
	writeToFile(jstringToChar(env, filePath),str,"w+");
	return true;
}

Android.mk日誌

 

 

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := libopfile
LOCAL_SRC_FILES := \
			JniFileTools.cpp

LOCAL_LDLIBS :=-llog
LOCAL_LDLIBS    += -lGLESv2 -llog -ldl
include $(BUILD_SHARED_LIBRARY)

 

注意使用權限:code

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

本案例中涉及到有:
1 delSubstr()刪除指定字符串;
2 jstring和char*之間的互相轉換;
3 讀寫模式a+和w+;
4 封裝輸出日誌到Logcat;

關於fopen()函數的幾個使用:

讀寫方式有下列幾種經常使用的形態:r 以只讀方式打開文件,該文件必須存在。r+ 以可讀寫方式打開文件,該文件必須存在。rb+ 讀寫打開一個二進制文件,容許讀寫數據,文件必須存在。w 打開只寫文件,若文件存在則文件長度清爲0,即該文件內容會消失。若文件不存在則創建該文件。w+ 打開可讀寫文件,若文件存在則文件長度清爲零,即該文件內容會消失。若文件不存在則創建該文件。a 以附加的方式打開只寫文件。若文件不存在,則會創建該文件,若是文件存在,寫入的數據會被加到文件尾,即文件原先的內容會被保留。(EOF符保留)a+ 以附加方式打開可讀寫的文件。若文件不存在,則會創建該文件,若是文件存在,寫入的數據會被加到文件尾後,即文件原先的內容會被保留。 (原來的EOF符不保留)

相關文章
相關標籤/搜索