分類:
Android的NDK開發(fā)
2012-05-01 16:46
3412人閱讀
收藏
舉報(bào)
/********************************************************************************************
* author:conowen@大鐘
* E-mail:conowen@hotmail.com
* http://blog.csdn.net/conowen
* 注:本文為原創(chuàng),僅作為學(xué)習(xí)交流使用,轉(zhuǎn)載請(qǐng)標(biāo)明作者及出處。
********************************************************************************************/
1、
在Android的java層實(shí)現(xiàn)文件的讀寫操作是非常簡(jiǎn)單的,可以參看之前寫的博文:http://blog.csdn.net/conowen/article/details/7296121
在JNI層實(shí)現(xiàn)文件的讀寫操作的話,就要使用到linux的讀寫函數(shù)了。
2、打開文件
- int open( const char *pathname,int flags, int mode);
返回值:為一個(gè)文件句柄(fd),供read、write等操作。
參數(shù):
pathname: 打開的文件所在路徑字符串。如
- String filename = "/sdcard/test.txt";
flags: 文件打開的方式
flag之間可以作“與”運(yùn)算,如
- open(filename, O_CREAT | O_RDWR,mode);
常用flags:
O_RDONLY 以只讀方式打開文件
O_WRONLY 以只寫方式打開文件
O_RDWR 以可讀寫方式打開文件。上述三種旗標(biāo)是互斥的,也就是不可同時(shí)使用,但可與下列的旗標(biāo)利用OR(|)運(yùn)算符組合。
O_CREAT 若欲打開的文件不存在則自動(dòng)建立該文件。
O_TRUNC 若文件存在并且以可寫的方式打開時(shí),此標(biāo)志位會(huì)令文件長(zhǎng)度重新清為0,也就是說文件內(nèi)容清空。
O_APPEND 當(dāng)讀寫文件時(shí)會(huì)從文件尾開始移動(dòng),也就是所寫入的數(shù)據(jù)會(huì)以附加的方式加入到文件后面。
O_NONBLOCK 以不可阻斷的方式打開文件,也就是無論有無數(shù)據(jù)讀取或等待,都會(huì)立即返回進(jìn)程之中。
O_SYNC 以同步的方式打開文件。
O_NOFOLLOW 如果參數(shù)pathname所指的文件為一符號(hào)連接,則會(huì)令打開文件失敗。
O_DIRECTORY 如果參數(shù)pathname所指的文件并非為一目錄,則會(huì)令打開文件失敗。
mode: 文件存儲(chǔ)權(quán)限
S_IRWXU00700 權(quán)限,代表該文件所有者具有可讀、可寫及可執(zhí)行的權(quán)限。
S_IRUSR 或S_IREAD,00400權(quán)限,代表該文件所有者具有可讀取的權(quán)限。
S_IWUSR 或S_IWRITE,00200 權(quán)限,代表該文件所有者具有可寫入的權(quán)限。
S_IXUSR 或S_IEXEC,00100 權(quán)限,代表該文件所有者具有可執(zhí)行的權(quán)限。
S_IRWXG 00070權(quán)限,代表該文件用戶組具有可讀、可寫及可執(zhí)行的權(quán)限。
S_IRGRP 00040 權(quán)限,代表該文件用戶組具有可讀的權(quán)限。
S_IWGRP 00020權(quán)限,代表該文件用戶組具有可寫入的權(quán)限。
S_IXGRP 00010 權(quán)限,代表該文件用戶組具有可執(zhí)行的權(quán)限。
S_IRWXO 00007權(quán)限,代表其他用戶具有可讀、可寫及可執(zhí)行的權(quán)限。
S_IROTH 00004 權(quán)限,代表其他用戶具有可讀的權(quán)限
S_IWOTH 00002權(quán)限,代表其他用戶具有可寫入的權(quán)限。
S_IXOTH 00001 權(quán)限,代表其他用戶具有可執(zhí)行的權(quán)限。
3、文件的讀(read)操作
- int read(int fd, unsigned char *buf, int size);
返回值:返回實(shí)際讀取到的字節(jié)數(shù),如果返回0,表示已到達(dá)文件尾或是無可讀取的數(shù)據(jù),此外文件讀寫位置會(huì)隨讀取到的字節(jié)移動(dòng)。
參數(shù):
fd:表示文件句柄,是由open函數(shù)得到
buf:read()函數(shù)會(huì)把fd 所指的文件傳送count個(gè)字節(jié)到buf指針?biāo)傅膬?nèi)存中
size:要讀取的字節(jié)數(shù)
4、寫入操作
- int write (int fd, const unsigned char *buf, int size);
返回值 :如果成功write(),就會(huì)返回實(shí)際寫入的字節(jié)數(shù)。當(dāng)有錯(cuò)誤發(fā)生時(shí)則返回-1
參數(shù):
fd:同上
buf:將要寫入到文件里面的內(nèi)容。
size:要寫入的字節(jié)數(shù)
5、跳轉(zhuǎn)操作
- int64_t seek(int fd, int64_t pos, int whence)
返回值:成功時(shí)則返回目前的讀寫位置,也就是距離文件開頭多少個(gè)字節(jié),若有錯(cuò)誤則返回-1。
參數(shù):
fd:同上
pos:跳轉(zhuǎn)的相對(duì)量,可正可負(fù),表示相對(duì)位置的前后關(guān)系
whence:跳轉(zhuǎn)的方向,whence取值如下所示
- int SEEK_SET = 0;
- int SEEK_CUR = 1;
- int EEK_END = 2;
注:當(dāng)size參數(shù)=0;whence = SEEK_END;時(shí)返回值即為文件大小。
6、關(guān)閉操作
7、簡(jiǎn)單示例
效果圖:
7.1、JNI代碼:(有JNI_onLoad函數(shù))
-
- #include <unistd.h>
- #include <sys/stat.h>
- #include <sys/time.h>
- #include <stdlib.h>
- #include <fcntl.h>
-
-
- int file_open(const char *filename, int flags)
- {
- int fd;
-
- fd = open(filename, flags, 0666);
- if (fd == -1)
- return -1;
-
- return fd;
- }
-
- int file_read(int fd, unsigned char *buf, int size)
- {
-
- return read(fd, buf, size);
- }
-
- int file_write(int fd, const unsigned char *buf, int size)
- {
-
- return write(fd, buf, size);
- }
-
-
- int64_t file_seek(int fd, int64_t pos, int whence)
- {
-
- if (whence == 0x10000) {
- struct stat st;
- int ret = fstat(fd, &st);
- return ret < 0 ? -1 : st.st_size;
- }
- return lseek(fd, pos, whence);
- }
-
- int file_close(int fd)
- {
-
- return close(fd);
- }
-
- #define TAG "fs_jni"
-
- #include <android/log.h>
- #include "jniUtils.h"
-
-
-
- static const char* const kClassPathName = "com/conowen/fs/FsActivity";
-
-
- jint
- Java_com_conowen_fs_FsActivity_NativeFileOpen( JNIEnv* env, jobject thiz,jstring filename,jint flags ){
-
-
- const char *filename_char = (*env)->GetStringUTFChars(env,filename, NULL);
-
- return file_open(filename_char, flags);
- }
- jint
- Java_com_conowen_fs_FsActivity_NativeFileRead(JNIEnv* env, jobject thiz,int fd,jbyteArray buf,jint size){
-
- unsigned char *buf_char = (char*)((*env)->GetByteArrayElements(env,buf, NULL));
-
- return file_read(fd, buf_char, size);
- }
-
- jint
- Java_com_conowen_fs_FsActivity_NativeFileWrite(JNIEnv* env, jobject thiz,int fd,jbyteArray buf,jint size){
-
- unsigned char *buf_char = (char*)((*env)->GetByteArrayElements(env,buf, NULL));
-
- return file_write(fd, buf_char, size);
- }
-
- jlong
- Java_com_conowen_fs_FsActivity_NativeFileSeek(JNIEnv* env, jobject thiz,int fd,jlong Offset,jint whence){
-
- return file_seek(fd, Offset, whence);
- }
-
- jint
- Java_com_conowen_fs_FsActivity_NativeFileClose(JNIEnv* env, jobject thiz,int fd){
-
- return file_close(fd);
- }
-
-
- static JNINativeMethod gMethods[] = {
- {"NativeFileOpen", "(Ljava/lang/String;I)I", (void *)Java_com_conowen_fs_FsActivity_NativeFileOpen},
- {"NativeFileRead", "(I[BI)I", (void *)Java_com_conowen_fs_FsActivity_NativeFileRead},
- {"NativeFileWrite", "(I[BI)I", (void *)Java_com_conowen_fs_FsActivity_NativeFileWrite},
- {"NativeFileSeek", "(IJI)J", (void *)Java_com_conowen_fs_FsActivity_NativeFileSeek},
- {"NativeFileClose", "(I)I", (void *)Java_com_conowen_fs_FsActivity_NativeFileClose},
- };
-
- int register_com_conowen_fs_FsActivity(JNIEnv *env) {
- return jniRegisterNativeMethods(env, kClassPathName, gMethods, sizeof(gMethods) / sizeof(gMethods[0]));
-
- }
-
- #ifndef _JNI_UTILS_H_
- #define _JNI_UTILS_H_
-
- #include <stdlib.h>
- #include <jni.h>
-
- #ifdef __cplusplus
- extern "C"
- {
- #endif
-
- int jniThrowException(JNIEnv* env, const char* className, const char* msg);
-
- JNIEnv* getJNIEnv();
-
- int jniRegisterNativeMethods(JNIEnv* env,
- const char* className,
- const JNINativeMethod* gMethods,
- int numMethods);
-
- #ifdef __cplusplus
- }
- #endif
-
- #endif /* _JNI_UTILS_H_ */
-
- #define TAG "fs_onLoad"
-
- #include <android/log.h>
- #include "jniUtils.h"
-
- extern "C" {
-
- extern int register_com_conowen_fs_FsActivity(JNIEnv *env);
-
- }
-
- static JavaVM *sVm;
-
-
-
-
- int jniThrowException(JNIEnv* env, const char* className, const char* msg) {
- jclass exceptionClass = env->FindClass(className);
- if (exceptionClass == NULL) {
- __android_log_print(ANDROID_LOG_ERROR,
- TAG,
- "Unable to find exception class %s",
- className);
- return -1;
- }
-
- if (env->ThrowNew(exceptionClass, msg) != JNI_OK) {
- __android_log_print(ANDROID_LOG_ERROR,
- TAG,
- "Failed throwing '%s' '%s'",
- className, msg);
- }
- return 0;
- }
-
- JNIEnv* getJNIEnv() {
- JNIEnv* env = NULL;
- if (sVm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
- __android_log_print(ANDROID_LOG_ERROR,
- TAG,
- "Failed to obtain JNIEnv");
- return NULL;
- }
- return env;
- }
-
-
-
-
-
-
- int jniRegisterNativeMethods(JNIEnv* env,
- const char* className,
- const JNINativeMethod* gMethods,
- int numMethods)
- {
- jclass clazz;
-
- __android_log_print(ANDROID_LOG_INFO, TAG, "Registering %s natives\n", className);
- clazz = env->FindClass(className);
- if (clazz == NULL) {
- __android_log_print(ANDROID_LOG_ERROR, TAG, "Native registration unable to find class '%s'\n", className);
- return -1;
- }
- if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) {
- __android_log_print(ANDROID_LOG_ERROR, TAG, "RegisterNatives failed for '%s'\n", className);
- return -1;
- }
- return 0;
- }
-
- jint JNI_OnLoad(JavaVM* vm, void* reserved) {
- JNIEnv* env = NULL;
- jint result = JNI_ERR;
- sVm = vm;
-
- if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
- __android_log_print(ANDROID_LOG_ERROR, TAG, "GetEnv failed!");
- return result;
- }
-
- __android_log_print(ANDROID_LOG_INFO, TAG, "loading . . .");
-
-
- if(register_com_conowen_fs_FsActivity(env) != JNI_OK) {
- __android_log_print(ANDROID_LOG_ERROR, TAG, "can't load register_com_conowen_fs_FsActivity");
- goto end;
- }
-
- __android_log_print(ANDROID_LOG_INFO, TAG, "loaded");
-
- result = JNI_VERSION_1_4;
-
- end:
- return result;
- }
7.2、Android.mk文件
- LOCAL_PATH := $(call my-dir)
-
- include $(CLEAR_VARS)
-
- LOCAL_MODULE := fs
- LOCAL_SRC_FILES := fs.c jni.c onLoad.cpp
- LOCAL_LDLIBS += -llog
-
- include $(BUILD_SHARED_LIBRARY)
7.3、java層代碼
-
-
-
-
- package com.conowen.fs;
-
- import java.io.UnsupportedEncodingException;
-
- import android.app.Activity;
- import android.os.Bundle;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.widget.Button;
- import android.widget.EditText;
- import android.widget.TextView;
-
- public class FsActivity extends Activity {
- String filename = "/sdcard/test.txt";
- EditText writestrET;
- Button writeBT;
- Button readBT;
- Button seekBT;
- TextView readTV;
- String writeStr;
- byte[] buf_write;
- byte[] buf_read;
- int fd;
-
- int O_ACCMODE = 0003;
- int O_RDONLY = 00;
- int O_WRONLY = 01;
- int O_RDWR = 02;
- int O_CREAT = 0100;
- int O_EXCL = 0200;
- int O_NOCTTY = 0400;
- int O_TRUNC = 01000;
- int O_APPEND = 02000;
- int O_NONBLOCK = 04000;
- int O_NDELAY = O_NONBLOCK;
- int O_SYNC = 010000;
- int O_FSYNC = O_SYNC;
- int O_ASYNC = 020000;
-
- int SEEK_SET = 0;
- int SEEK_CUR = 1;
- int EEK_END = 2;
-
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- writestrET = (EditText) findViewById(R.id.writeET);
- writeBT = (Button) findViewById(R.id.writeBT);
- readBT = (Button) findViewById(R.id.readBT);
- seekBT = (Button) findViewById(R.id.seekBT);
- readTV = (TextView) findViewById(R.id.readTV);
- writeBT.setOnClickListener(new OnClickListener() {
-
- @Override
- public void onClick(View v) {
-
- fd = NativeFileOpen(filename, O_CREAT | O_RDWR);
- System.out.println("fd_write---->" + fd);
- writeStr = writestrET.getText().toString();
- buf_write = writeStr.getBytes();
- int ret_write = NativeFileWrite(fd, buf_write, buf_write.length);
- System.out.println("寫入返回結(jié)果" + ret_write);
- NativeFileClose(fd);
-
- }
- });
- readBT.setOnClickListener(new OnClickListener() {
-
- @Override
- public void onClick(View v) {
-
- fd = NativeFileOpen(filename, O_CREAT | O_RDWR);
- System.out.println("fd_read---->" + fd);
- buf_read = new byte[buf_write.length];
- int ret_read = NativeFileRead(fd, buf_read, buf_write.length);
-
- System.out.println("讀出返回結(jié)果" + ret_read);
- try {
- readTV.setText( new String(buf_read, "GB2312") + "");
- } catch (UnsupportedEncodingException e) {
-
- e.printStackTrace();
- }
- NativeFileClose(fd);
- }
- });
- seekBT.setOnClickListener(new OnClickListener() {
-
- @Override
- public void onClick(View v) {
-
- fd = NativeFileOpen(filename, O_CREAT | O_RDWR);
- long Offset=20;
- long ret_seek =NativeFileSeek(fd, Offset, SEEK_CUR);
-
- System.out.println("seek返回結(jié)果" + ret_seek);
-
- NativeFileClose(fd);
-
-
-
-
-
-
-
-
- }
- });
-
- }
-
- public native int NativeFileOpen(String filename, int flags);
-
- public native int NativeFileRead(int fd, byte[] buf, int sizes);
-
- public native int NativeFileWrite(int fd, byte[] buf, int sizes);
-
- public native long NativeFileSeek(int fd, long Offset, int whence);
-
-
- public native int NativeFileClose(int fd);
-
- static {
- System.loadLibrary("fs");
- }
- }
最后記得在manifest.xml里面加上SD卡操作權(quán)限
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
- <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
|