原文网址: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 != ‘\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)
注意使用权限:
<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符不保留)
原文:http://www.cnblogs.com/wi100sh/p/5191367.html