Java jni文件流读写_Android的NDK开发(5)————Android JNI层实现文件的read、write与seek操作...

本文介绍了如何在Android的JNI层使用Linux的读写函数来操作文件,包括打开文件、读取(read)、写入(write)、跳转(seek)和关闭(close)文件的操作。通过示例代码详细展示了JNI接口的实现,包括在C语言中定义的函数以及Java层的调用方法。
摘要由CSDN通过智能技术生成

1、

在JNI层实现文件的读写操作的话,就要使用到linux的读写函数了。

2、打开文件

intopen(constchar*pathname,intflags,intmode);

返回值:为一个文件句柄(fd),供read、write等操作。

参数:

pathname: 打开的文件所在路径字符串。如

String filename ="/sdcard/test.txt";

flags: 文件打开的方式

flag之间可以作“与”运算,如

open(filename, O_CREAT  | O_RDWR,mode);

常用flags:

O_RDONLY 以只读方式打开文件

O_WRONLY 以只写方式打开文件

O_RDWR 以可读写方式打开文件。上述三种旗标是互斥的,也就是不可同时使用,但可与下列的旗标利用OR(|)运算符组合。

O_CREAT 若欲打开的文件不存在则自动建立该文件。

O_TRUNC 若文件存在并且以可写的方式打开时,此标志位会令文件长度重新清为0,也就是说文件内容清空。

O_APPEND 当读写文件时会从文件尾开始移动,也就是所写入的数据会以附加的方式加入到文件后面。

O_NONBLOCK 以不可阻断的方式打开文件,也就是无论有无数据读取或等待,都会立即返回进程之中。

O_SYNC 以同步的方式打开文件。

O_NOFOLLOW 如果参数pathname所指的文件为一符号连接,则会令打开文件失败。

O_DIRECTORY 如果参数pathname所指的文件并非为一目录,则会令打开文件失败。

mode: 文件存储权限

S_IRWXU00700 权限,代表该文件所有者具有可读、可写及可执行的权限。

S_IRUSR 或S_IREAD,00400权限,代表该文件所有者具有可读取的权限。

S_IWUSR 或S_IWRITE,00200 权限,代表该文件所有者具有可写入的权限。

S_IXUSR 或S_IEXEC,00100 权限,代表该文件所有者具有可执行的权限。

S_IRWXG 00070权限,代表该文件用户组具有可读、可写及可执行的权限。

S_IRGRP 00040 权限,代表该文件用户组具有可读的权限。

S_IWGRP 00020权限,代表该文件用户组具有可写入的权限。

S_IXGRP 00010 权限,代表该文件用户组具有可执行的权限。

S_IRWXO 00007权限,代表其他用户具有可读、可写及可执行的权限。

S_IROTH 00004 权限,代表其他用户具有可读的权限

S_IWOTH 00002权限,代表其他用户具有可写入的权限。

S_IXOTH 00001 权限,代表其他用户具有可执行的权限。

3、文件的读(read)操作

intread(intfd, unsignedchar*buf,intsize);

返回值:返回实际读取到的字节数,如果返回0,表示已到达文件尾或是无可读取的数据,此外文件读写位置会随读取到的字节移动。

参数:

fd:表示文件句柄,是由open函数得到

buf:read()函数会把fd 所指的文件传送count个字节到buf指针所指的内存中

size:要读取的字节数

4、写入操作

intwrite (intfd,constunsignedchar*buf,intsize);

返回值:如果成功write(),就会返回实际写入的字节数。当有错误发生时则返回-1

参数:

fd:同上

buf:将要写入到文件里面的内容。

size:要写入的字节数

5、跳转操作

int64_t seek(intfd, int64_t pos,intwhence)

返回值:成功时则返回目前的读写位置,也就是距离文件开头多少个字节,若有错误则返回-1。

参数:

fd:同上

pos:跳转的相对量,可正可负,表示相对位置的前后关系

whence:跳转的方向,whence取值如下所示

intSEEK_SET   =        0;//将读写位置指向文件头后再增加offset个位移量。

intSEEK_CUR   =        1;//以目前的读写位置往后增加offset个位移量。

intEEK_END    =        2;//将读写位置指向文件尾后再增加offset个位移量。

注:当size参数=0;whence = SEEK_END;时返回值即为文件大小。

6、关闭操作

intclose(intfd)

7、简单示例

效果图:

1335862911_8605.jpg

1335862924_1015.jpg

7.1、JNI代码:(有JNI_onLoad函数)

//fs.c

#include 

#include 

#include 

#include 

#include 

intfile_open(constchar*filename,intflags)

{

intfd;

fd = open(filename, flags, 0666);

if(fd == -1)

return-1;

returnfd;

}

intfile_read(intfd, unsignedchar*buf,intsize)

{

returnread(fd, buf, size);

}

intfile_write(intfd,constunsignedchar*buf,intsize)

{

returnwrite(fd, buf, size);

}

int64_t file_seek(intfd, int64_t pos,intwhence)

{

if(whence == 0x10000) {

structstat st;

intret = fstat(fd, &st);

returnret 

}

returnlseek(fd, pos, whence);

}

intfile_close(intfd)

{

returnclose(fd);

}

//jni.c

#define TAG "fs_jni"

#include 

#include "jniUtils.h"

staticconstchar*constkClassPathName ="com/conowen/fs/FsActivity";

jint

Java_com_conowen_fs_FsActivity_NativeFileOpen( JNIEnv* env, jobject thiz,jstring filename,jint flags ){

constchar*filename_char = (*env)->GetStringUTFChars(env,filename, NULL);

returnfile_open(filename_char, flags);

}

jint

Java_com_conowen_fs_FsActivity_NativeFileRead(JNIEnv* env, jobject thiz,intfd,jbyteArray buf,jint size){

unsigned char*buf_char = (char*)((*env)->GetByteArrayElements(env,buf, NULL));

returnfile_read(fd, buf_char,  size);

}

jint

Java_com_conowen_fs_FsActivity_NativeFileWrite(JNIEnv* env, jobject thiz,intfd,jbyteArray buf,jint size){

unsigned char*buf_char = (char*)((*env)->GetByteArrayElements(env,buf, NULL));

returnfile_write(fd, buf_char,  size);

}

jlong

Java_com_conowen_fs_FsActivity_NativeFileSeek(JNIEnv* env, jobject thiz,intfd,jlong Offset,jint whence){

returnfile_seek(fd, Offset,  whence);

}

jint

Java_com_conowen_fs_FsActivity_NativeFileClose(JNIEnv* env, jobject thiz,intfd){

returnfile_close(fd);

}

/******************************JNI registration.************************************/

staticJNINativeMethod 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},

};

intregister_com_conowen_fs_FsActivity(JNIEnv *env) {

returnjniRegisterNativeMethods(env, kClassPathName, gMethods,sizeof(gMethods) /sizeof(gMethods[0]));

}

//jniUtils.h

#ifndef _JNI_UTILS_H_

#define _JNI_UTILS_H_

#include 

#include 

#ifdef __cplusplus

extern"C"

{

#endif

intjniThrowException(JNIEnv* env,constchar* className,constchar* msg);

JNIEnv* getJNIEnv();

intjniRegisterNativeMethods(JNIEnv* env,

constchar* className,

constJNINativeMethod* gMethods,

intnumMethods);

#ifdef __cplusplus

}

#endif

#endif /* _JNI_UTILS_H_ */

//onLoad.cpp

#define TAG "fs_onLoad"

#include 

#include "jniUtils.h"

extern"C"{

externintregister_com_conowen_fs_FsActivity(JNIEnv *env);

}

staticJavaVM *sVm;

/*

* Throw an exception with the specified class and an optional message.

*/

intjniThrowException(JNIEnv* env,constchar* className,constchar* 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);

}

return0;

}

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");

returnNULL;

}

returnenv;

}

/*

* Register native JNI-callable methods.

*

* "className" looks like "java/lang/String".

*/

intjniRegisterNativeMethods(JNIEnv* env,

constchar* className,

constJNINativeMethod* gMethods,

intnumMethods)

{

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) 

__android_log_print(ANDROID_LOG_ERROR, TAG, "RegisterNatives failed for '%s'\n", className);

return-1;

}

return0;

}

//Dalvik虚拟机加载C库时,第一件事是调用JNI_OnLoad()函数

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!");

returnresult;

}

__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");

gotoend;

}

__android_log_print(ANDROID_LOG_INFO, TAG, "loaded");

result = JNI_VERSION_1_4;

end:

returnresult;

}

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层代码

/* author:conowen

* data:2012.5.1

* e-mail:conowen@hotmail.com

*/

packagecom.conowen.fs;

importjava.io.UnsupportedEncodingException;

importandroid.app.Activity;

importandroid.os.Bundle;

importandroid.view.View;

importandroid.view.View.OnClickListener;

importandroid.widget.Button;

importandroid.widget.EditText;

importandroid.widget.TextView;

publicclassFsActivityextendsActivity {

String filename = "/sdcard/test.txt";

EditText writestrET;

Button writeBT;

Button readBT;

Button seekBT;

TextView readTV;

String writeStr;

byte[] buf_write;

byte[] buf_read;

intfd;

intO_ACCMODE  =0003;

intO_RDONLY   =00;

intO_WRONLY   =01;

intO_RDWR     =02;

intO_CREAT    =0100;/* not fcntl */

intO_EXCL     =0200;/* not fcntl */

intO_NOCTTY   =0400;/* not fcntl */

intO_TRUNC    =01000;/* not fcntl */

intO_APPEND   =02000;

intO_NONBLOCK =04000;

intO_NDELAY   = O_NONBLOCK;

intO_SYNC     =010000;

intO_FSYNC    =  O_SYNC;

intO_ASYNC    =020000;

intSEEK_SET   =0;//将读写位置指向文件头后再增加offset个位移量。

intSEEK_CUR   =1;//以目前的读写位置往后增加offset个位移量。

intEEK_END    =2;//将读写位置指向文件尾后再增加offset个位移量。

/** Called when the activity is first created. */

@Override

publicvoidonCreate(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(newOnClickListener() {

@Override

publicvoidonClick(View v) {

// TODO Auto-generated method stub

fd = NativeFileOpen(filename, O_CREAT  | O_RDWR);

System.out.println("fd_write---->"+ fd);

writeStr = writestrET.getText().toString();

buf_write = writeStr.getBytes();

intret_write = NativeFileWrite(fd, buf_write, buf_write.length);

System.out.println("写入返回结果"+ ret_write);

NativeFileClose(fd);

}

});

readBT.setOnClickListener(newOnClickListener() {

@Override

publicvoidonClick(View v) {

// TODO Auto-generated method stub

fd = NativeFileOpen(filename, O_CREAT  | O_RDWR);

System.out.println("fd_read---->"+ fd);

buf_read = newbyte[buf_write.length];

intret_read = NativeFileRead(fd, buf_read, buf_write.length);

System.out.println("读出返回结果"+ ret_read);

try{

readTV.setText( newString(buf_read,"GB2312") +"");

} catch(UnsupportedEncodingException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

NativeFileClose(fd);

}

});

seekBT.setOnClickListener(newOnClickListener() {

@Override

publicvoidonClick(View v) {

// TODO Auto-generated method stub

fd = NativeFileOpen(filename, O_CREAT  | O_RDWR);

longOffset=20;

longret_seek =NativeFileSeek(fd, Offset, SEEK_CUR);

System.out.println("seek返回结果"+ ret_seek);

NativeFileClose(fd);

/*    1) 欲将读写位置移到文件开头时:

lseek(int fildes,0,SEEK_SET);

2) 欲将读写位置移到文件尾时:

lseek(int fildes,0,SEEK_END);

3) 想要取得目前文件位置时:

lseek(int fildes,0,SEEK_CUR);

返回值:当调用成功时则返回目前的读写位置,也就是距离文件开头多少个字节。若有错误则返回-1,errno 会存放错误代码。

* */

}

});

}

publicnativeintNativeFileOpen(String filename,intflags);

publicnativeintNativeFileRead(intfd,byte[] buf,intsizes);

publicnativeintNativeFileWrite(intfd,byte[] buf,intsizes);

publicnativelongNativeFileSeek(intfd,longOffset,intwhence);

//Offset:偏移量,每一读写操作所需要移动的距离,单位是字节的数量,可正可负(向前移,向后移)。

publicnativeintNativeFileClose(intfd);

static{

System.loadLibrary("fs");

}

}

最后记得在manifest.xml里面加上SD卡操作权限

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值