【转】文件读写NDK(或Linux)

原文网址:http://www.ithao123.cn/content-10709539.html

使用NDK进行文件读写,有利于保存数据的安全性,项目需要,要文件读写从Java中处理搬到Linux平台,为了方便两个平台的代码维护一致,使用JNI进行重写编写;

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接口:

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个方法:

Java_jni_file_tools_JniFileTools_readFile();

Java_jni_file_tools_JniFileTools_writeFile();

Java_jni_file_tools_JniFileTools_deleteString();

JniFileTools.cpp

#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 != '') {
		p = src;
		q = delstr;
		while (*p == *q && *q != '') {
			p++;
			q++;
		}
		if (*q == '') {
			src = p;
		} else {
			*dst++ = *src++;
		}
	}
	*dst = '';
	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)

注意使用权限:

<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符不保留)

原文地址:https://www.cnblogs.com/wi100sh/p/5191367.html