Android的NDK开发(5)————Android JNI层实现文件的read、write与seek操作
1、
在Android的Java层实现文件的读写操作是非常简单的,可以参看之前写的博文:http://blog.csdn.net/conowen/article/details/7296121
在JNI层实现文件的读写操作的话,就要使用到Linux的读写函数了。
2、打开文件
- int open( const char *pathname,int flags, int mode);
返回值:为一个文件句柄(fd),供read、write等操作。
参数:
pathname: 打开的文件所在路径字符串。如
- String filename = "/sdcard/test.txt";
flags: 文件打开的方式
flag之间可以作“与”运算,如
- open(filename, O_CREAT | O_RDWR,mode);
3、文件的读(read)操作
- int read(int fd, unsigned char *buf, int size);
返回值:返回实际读取到的字节数,如果返回0,表示已到达文件尾或是无可读取的数据,此外文件读写位置会随读取到的字节移动。
参数:
fd:表示文件句柄,是由open函数得到
buf:read()函数会把fd 所指的文件传送count个字节到buf指针所指的内存中
size:要读取的字节数
4、写入操作
- int write (int fd, const unsigned char *buf, int size);
返回值 :如果成功write(),就会返回实际写入的字节数。当有错误发生时则返回-1
参数:
fd:同上
buf:将要写入到文件里面的内容。
size:要写入的字节数
5、跳转操作
- int64_t seek(int fd, int64_t pos, int whence)
返回值:成功时则返回目前的读写位置,也就是距离文件开头多少个字节,若有错误则返回-1。
参数:
- int SEEK_SET = 0;//将读写位置指向文件头后再增加offset个位移量。
- int SEEK_CUR = 1;//以目前的读写位置往后增加offset个位移量。
- int EEK_END = 2;//将读写位置指向文件尾后再增加offset个位移量。
注:当size参数=0;whence = SEEK_END;时返回值即为文件大小。
6、关闭操作
- int close(int fd)
7、简单示例
效果图:
7.1、JNI代码:(有JNI_onLoad函数)
- //fs.c
- #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);
- }
- //jni.c
- #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);
- }
- /******************************JNI registration.************************************/
- 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]));
- }
- //jniUtils.h
- #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_ */
- //onLoad.cpp
- #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;
- /*
- * Throw an exception with the specified class and an optional message.
- */
- 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;
- }
- /*
- * Register native JNI-callable methods.
- *
- * "className" looks like "java/lang/String".
- */
- 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;
- }
- //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!");
- 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层代码
- /* author:conowen
- * data:2012.5.1
- * e-mail:conowen@hotmail.com
- */
- 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; /* not fcntl */
- int O_EXCL = 0200; /* not fcntl */
- int O_NOCTTY = 0400; /* not fcntl */
- int O_TRUNC = 01000; /* not fcntl */
- 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;//将读写位置指向文件头后再增加offset个位移量。
- int SEEK_CUR = 1;//以目前的读写位置往后增加offset个位移量。
- int EEK_END = 2;//将读写位置指向文件尾后再增加offset个位移量。
- /** Called when the activity is first created. */
- @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) {
- // 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();
- int ret_write = NativeFileWrite(fd, buf_write, buf_write.length);
- System.out.println("写入返回结果" + ret_write);
- NativeFileClose(fd);
- }
- });
- readBT.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- // TODO Auto-generated method stub
- 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("读出返回结果" + ret_read);
- try {
- readTV.setText( new String(buf_read, "GB2312") + "");
- } catch (UnsupportedEncodingException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- NativeFileClose(fd);
- }
- });
- seekBT.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- // TODO Auto-generated method stub
- fd = NativeFileOpen(filename, O_CREAT | O_RDWR);
- long Offset=20;
- long ret_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 会存放错误代码。
- * */
- }
- });
- }
- 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);
- //Offset:偏移量,每一读写操作所需要移动的距离,单位是字节的数量,可正可负(向前移,向后移)。
- public native int NativeFileClose(int fd);
- static {
- System.loadLibrary("fs");
- }
- }
最后记得在manifest.xml里面加上SD卡操作权限
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
- <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
Android的NDK开发(5)————Android JNI层实现文件的read、write与seek操作的更多相关文章
- 【转】 Android的NDK开发(1)————Android JNI简介与调用流程
原文网址:http://blog.csdn.net/conowen/article/details/7521340 ****************************************** ...
- Android的NDK开发(1)————Android JNI简介与调用流程
1.JNI简介 JNI全称为Java Native Interface(Java本地调用).从Java1.1开始,JNI成为java平台的一部分,它允许Java代码和其他语言写的代码(如C&C ...
- android的ndk开发简介-android学习之旅(93)
环境搭建 1.安装ndk 2.安装cygwin (android是基于linux的Framework,运行的本地库是.SO,而不是.dll库,大部分都实在windows下开发,如果是linux就没这个 ...
- Android之NDK开发(转)
Android之NDK开发 一.NDK产生的背景 Android平台从诞生起,就已经支持C.C++开发.众所周知,Android的SDK基于Java实现,这意味着基于Android SDK进行开发的第 ...
- Android之NDK开发
转自:http://www.cnblogs.com/devinzhang/archive/2012/02/29/2373729.html 一.NDK产生的背景 Android平台从诞生起,就已经支持C ...
- 【转】Android之NDK开发
原文网址:http://www.cnblogs.com/devinzhang/archive/2012/02/29/2373729.html 一.NDK产生的背景 Android平台从诞生起,就已经支 ...
- android studio ndk 开发入门
ndk 开发没什么神秘的ndk 说白了就是一个交叉编译的工具链,用它来生成各个CPU架构下的静态或动态链接库,linux 下就是 .a 和 .so 文件.原理就是 java 通过 JNI 和 C.C+ ...
- Android之NDK开发(转载)
http://www.cnblogs.com/devinzhang/archive/2012/02/29/2373729.html 一.NDK产生的背景 Android平台从诞生起,就已经支持C.C+ ...
- 【Android】Android Studio NDK 开发
Android Studio NDK 开发 记录在Android Studio中NDK简单开发的步骤 用到的Android Studio版本为3.5. 配置NDK 下载NDK 一般在SDK下已经有自带 ...
随机推荐
- libiconv 支持的编码
libiconv 支持的编码 php 中的 iconv() 函数常用来作编码转换用.作一些不同编码的动态数据的转换时常遇到一些未知编码的数据,这时 iconv() 支持那些编码转换就很重要. 刚开始, ...
- 【例题 7-8 UVA - 10603】Fill
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 三维显然可以缩短为2维. 只要知道a,b瓶中的水量,c瓶中的水量减一下就能得到. 则设dis[a][b]表示a,b瓶中水量为a,b时 ...
- Java Web学习总结(12)——使用Session防止表单重复提交
在平时开发中,如果网速比较慢的情况下,用户提交表单后,发现服务器半天都没有响应,那么用户可能会以为是自己没有提交表单,就会再点击提交按钮重复提交表单,我们在开发中必须防止表单重复提交. 一.表单重复提 ...
- 【原创】基于pyautogui进行自动化测试
前期准备: python3.6 pyautogui pywinauto 以下代码实现内容: 1.打开记事本 2.记事本中输入This is a test 3.保存内容 4.退出进程 import py ...
- Redo 非current损坏
Redo log 文件损坏或丢失,在启动数据库时在alert日志中会有如下错误: ORA-00313: open failed for members of log group 1 of thread ...
- HDU 1556 Color the ball【算法的优化】
/* 解题思路:每次仅仅求解一開始的第一个数字,让第一个数字加一,最后的一个数字的后面一个数减一.我们能够想想,最后加的时候,就是加上前面一个数出现的次数和自己本身出现的次数. 解题人:lingnic ...
- 内存问题检查利器——Purify
内存问题检查利器——Purify 一. 引言 我们都知道软件的测试(在以产品为主的软件公司中叫做QA—Quality Assessment)占了整个软件工程的30% -50%,但有 ...
- linux 内核源代码目录结构
/arch:目录包括了所有和体系结构相关的核心代码.它下面的每一个子目录都代表一种Linux支持的体系结构,例如i386就是Intel CPU及与之相兼容体系结构的子目录.PC机一般都基于此目录. / ...
- 再谈ITFriend网站的定位
在网站开发阶段.内部测试阶段.公开测试阶段,让诸多好友和网友,参与了我们的网站ITFriend的体验和测试.其中,大家非常关心,我们的网站是干什么的.在我们不做任何解释的情况下,有的网站认为ITFri ...
- Android layer-list的属性和使用具体解释
Android layer-list的属性和使用具体解释.layer-list是用来多个图层堆叠显示的,借这个特性能够做一些特别的效果(比方:阴影.以下的效果等),也能够投机取巧. 1.代码片 < ...