1、

AndroidJava层实现文件的读写操作是非常简单的,可以参看之前写的博文:http://blog.csdn.net/conowen/article/details/7296121

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

2、打开文件

  1. int open( const char *pathname,int flags, int mode);

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

参数:

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

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

flags: 文件打开的方式

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

  1. open(filename, O_CREAT  | O_RDWR,mode);

3、文件的读(read)操作

  1. int read(int fd, unsigned char *buf, int size);


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

参数:

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

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

size:要读取的字节数

4、写入操作

  1. int write (int fd, const unsigned char *buf, int size);


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

参数:

fd:同上

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

size:要写入的字节数

5、跳转操作

  1. int64_t seek(int fd, int64_t pos, int whence)


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

参数:

  1. int SEEK_SET   =        0;//将读写位置指向文件头后再增加offset个位移量。
  2. int SEEK_CUR   =        1;//以目前的读写位置往后增加offset个位移量。
  3. int EEK_END    =        2;//将读写位置指向文件尾后再增加offset个位移量。


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

6、关闭操作

  1. int close(int fd)

7、简单示例

效果图:

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

  1. //fs.c
  2. #include <unistd.h>
  3. #include <sys/stat.h>
  4. #include <sys/time.h>
  5. #include <stdlib.h>
  6. #include <fcntl.h>
  7. int file_open(const char *filename, int flags)
  8. {
  9. int fd;
  10. fd = open(filename, flags, 0666);
  11. if (fd == -1)
  12. return -1;
  13. return fd;
  14. }
  15. int file_read(int fd, unsigned char *buf, int size)
  16. {
  17. return read(fd, buf, size);
  18. }
  19. int file_write(int fd, const unsigned char *buf, int size)
  20. {
  21. return write(fd, buf, size);
  22. }
  23. int64_t file_seek(int fd, int64_t pos, int whence)
  24. {
  25. if (whence == 0x10000) {
  26. struct stat st;
  27. int ret = fstat(fd, &st);
  28. return ret < 0 ? -1 : st.st_size;
  29. }
  30. return lseek(fd, pos, whence);
  31. }
  32. int file_close(int fd)
  33. {
  34. return close(fd);
  35. }


  1. //jni.c
  2. #define TAG "fs_jni"
  3. #include <android/log.h>
  4. #include "jniUtils.h"
  5. static const char* const kClassPathName = "com/conowen/fs/FsActivity";
  6. jint
  7. Java_com_conowen_fs_FsActivity_NativeFileOpen( JNIEnv* env, jobject thiz,jstring filename,jint flags ){
  8. const char *filename_char = (*env)->GetStringUTFChars(env,filename, NULL);
  9. return file_open(filename_char, flags);
  10. }
  11. jint
  12. Java_com_conowen_fs_FsActivity_NativeFileRead(JNIEnv* env, jobject thiz,int fd,jbyteArray buf,jint size){
  13. unsigned char *buf_char = (char*)((*env)->GetByteArrayElements(env,buf, NULL));
  14. return file_read(fd, buf_char,  size);
  15. }
  16. jint
  17. Java_com_conowen_fs_FsActivity_NativeFileWrite(JNIEnv* env, jobject thiz,int fd,jbyteArray buf,jint size){
  18. unsigned char *buf_char = (char*)((*env)->GetByteArrayElements(env,buf, NULL));
  19. return file_write(fd, buf_char,  size);
  20. }
  21. jlong
  22. Java_com_conowen_fs_FsActivity_NativeFileSeek(JNIEnv* env, jobject thiz,int fd,jlong Offset,jint whence){
  23. return file_seek(fd, Offset,  whence);
  24. }
  25. jint
  26. Java_com_conowen_fs_FsActivity_NativeFileClose(JNIEnv* env, jobject thiz,int fd){
  27. return file_close(fd);
  28. }
  29. /******************************JNI registration.************************************/
  30. static JNINativeMethod gMethods[] = {
  31. {"NativeFileOpen",       "(Ljava/lang/String;I)I",           (void *)Java_com_conowen_fs_FsActivity_NativeFileOpen},
  32. {"NativeFileRead",       "(I[BI)I",                          (void *)Java_com_conowen_fs_FsActivity_NativeFileRead},
  33. {"NativeFileWrite",      "(I[BI)I",                          (void *)Java_com_conowen_fs_FsActivity_NativeFileWrite},
  34. {"NativeFileSeek",       "(IJI)J",                           (void *)Java_com_conowen_fs_FsActivity_NativeFileSeek},
  35. {"NativeFileClose",      "(I)I",                             (void *)Java_com_conowen_fs_FsActivity_NativeFileClose},
  36. };
  37. int register_com_conowen_fs_FsActivity(JNIEnv *env) {
  38. return jniRegisterNativeMethods(env, kClassPathName, gMethods, sizeof(gMethods) / sizeof(gMethods[0]));
  39. }


  1. //jniUtils.h
  2. #ifndef _JNI_UTILS_H_
  3. #define _JNI_UTILS_H_
  4. #include <stdlib.h>
  5. #include <jni.h>
  6. #ifdef __cplusplus
  7. extern "C"
  8. {
  9. #endif
  10. int jniThrowException(JNIEnv* env, const char* className, const char* msg);
  11. JNIEnv* getJNIEnv();
  12. int jniRegisterNativeMethods(JNIEnv* env,
  13. const char* className,
  14. const JNINativeMethod* gMethods,
  15. int numMethods);
  16. #ifdef __cplusplus
  17. }
  18. #endif
  19. #endif /* _JNI_UTILS_H_ */


  1. //onLoad.cpp
  2. #define TAG "fs_onLoad"
  3. #include <android/log.h>
  4. #include "jniUtils.h"
  5. extern "C" {
  6. extern int register_com_conowen_fs_FsActivity(JNIEnv *env);
  7. }
  8. static JavaVM *sVm;
  9. /*
  10. * Throw an exception with the specified class and an optional message.
  11. */
  12. int jniThrowException(JNIEnv* env, const char* className, const char* msg) {
  13. jclass exceptionClass = env->FindClass(className);
  14. if (exceptionClass == NULL) {
  15. __android_log_print(ANDROID_LOG_ERROR,
  16. TAG,
  17. "Unable to find exception class %s",
  18. className);
  19. return -1;
  20. }
  21. if (env->ThrowNew(exceptionClass, msg) != JNI_OK) {
  22. __android_log_print(ANDROID_LOG_ERROR,
  23. TAG,
  24. "Failed throwing '%s' '%s'",
  25. className, msg);
  26. }
  27. return 0;
  28. }
  29. JNIEnv* getJNIEnv() {
  30. JNIEnv* env = NULL;
  31. if (sVm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
  32. __android_log_print(ANDROID_LOG_ERROR,
  33. TAG,
  34. "Failed to obtain JNIEnv");
  35. return NULL;
  36. }
  37. return env;
  38. }
  39. /*
  40. * Register native JNI-callable methods.
  41. *
  42. * "className" looks like "java/lang/String".
  43. */
  44. int jniRegisterNativeMethods(JNIEnv* env,
  45. const char* className,
  46. const JNINativeMethod* gMethods,
  47. int numMethods)
  48. {
  49. jclass clazz;
  50. __android_log_print(ANDROID_LOG_INFO, TAG, "Registering %s natives\n", className);
  51. clazz = env->FindClass(className);
  52. if (clazz == NULL) {
  53. __android_log_print(ANDROID_LOG_ERROR, TAG, "Native registration unable to find class '%s'\n", className);
  54. return -1;
  55. }
  56. if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) {
  57. __android_log_print(ANDROID_LOG_ERROR, TAG, "RegisterNatives failed for '%s'\n", className);
  58. return -1;
  59. }
  60. return 0;
  61. }
  62. //Dalvik虚拟机加载C库时,第一件事是调用JNI_OnLoad()函数
  63. jint JNI_OnLoad(JavaVM* vm, void* reserved) {
  64. JNIEnv* env = NULL;
  65. jint result = JNI_ERR;
  66. sVm = vm;
  67. if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
  68. __android_log_print(ANDROID_LOG_ERROR, TAG, "GetEnv failed!");
  69. return result;
  70. }
  71. __android_log_print(ANDROID_LOG_INFO, TAG, "loading . . .");
  72. if(register_com_conowen_fs_FsActivity(env) != JNI_OK) {
  73. __android_log_print(ANDROID_LOG_ERROR, TAG, "can't load register_com_conowen_fs_FsActivity");
  74. goto end;
  75. }
  76. __android_log_print(ANDROID_LOG_INFO, TAG, "loaded");
  77. result = JNI_VERSION_1_4;
  78. end:
  79. return result;
  80. }


7.2、Android.mk文件

  1. LOCAL_PATH := $(call my-dir)
  2. include $(CLEAR_VARS)
  3. LOCAL_MODULE    := fs
  4. LOCAL_SRC_FILES := fs.c jni.c onLoad.cpp
  5. LOCAL_LDLIBS  += -llog
  6. include $(BUILD_SHARED_LIBRARY)

7.3、java层代码

  1. /* author:conowen
  2. * data:2012.5.1
  3. * e-mail:conowen@hotmail.com
  4. */
  5. package com.conowen.fs;
  6. import java.io.UnsupportedEncodingException;
  7. import android.app.Activity;
  8. import android.os.Bundle;
  9. import android.view.View;
  10. import android.view.View.OnClickListener;
  11. import android.widget.Button;
  12. import android.widget.EditText;
  13. import android.widget.TextView;
  14. public class FsActivity extends Activity {
  15. String filename = "/sdcard/test.txt";
  16. EditText writestrET;
  17. Button writeBT;
  18. Button readBT;
  19. Button seekBT;
  20. TextView readTV;
  21. String writeStr;
  22. byte[] buf_write;
  23. byte[] buf_read;
  24. int fd;
  25. int O_ACCMODE  =    0003;
  26. int O_RDONLY   =      00;
  27. int O_WRONLY   =      01;
  28. int O_RDWR     =      02;
  29. int O_CREAT    =    0100; /* not fcntl */
  30. int O_EXCL     =    0200; /* not fcntl */
  31. int O_NOCTTY   =   0400; /* not fcntl */
  32. int O_TRUNC    =   01000; /* not fcntl */
  33. int O_APPEND   =   02000;
  34. int O_NONBLOCK =   04000;
  35. int O_NDELAY   = O_NONBLOCK;
  36. int O_SYNC     =  010000;
  37. int O_FSYNC    =  O_SYNC;
  38. int O_ASYNC    =  020000;
  39. int SEEK_SET   =        0;//将读写位置指向文件头后再增加offset个位移量。
  40. int SEEK_CUR   =        1;//以目前的读写位置往后增加offset个位移量。
  41. int EEK_END    =        2;//将读写位置指向文件尾后再增加offset个位移量。
  42. /** Called when the activity is first created. */
  43. @Override
  44. public void onCreate(Bundle savedInstanceState) {
  45. super.onCreate(savedInstanceState);
  46. setContentView(R.layout.main);
  47. writestrET = (EditText) findViewById(R.id.writeET);
  48. writeBT = (Button) findViewById(R.id.writeBT);
  49. readBT = (Button) findViewById(R.id.readBT);
  50. seekBT = (Button) findViewById(R.id.seekBT);
  51. readTV = (TextView) findViewById(R.id.readTV);
  52. writeBT.setOnClickListener(new OnClickListener() {
  53. @Override
  54. public void onClick(View v) {
  55. // TODO Auto-generated method stub
  56. fd = NativeFileOpen(filename, O_CREAT  | O_RDWR);
  57. System.out.println("fd_write---->" + fd);
  58. writeStr = writestrET.getText().toString();
  59. buf_write = writeStr.getBytes();
  60. int ret_write = NativeFileWrite(fd, buf_write, buf_write.length);
  61. System.out.println("写入返回结果" + ret_write);
  62. NativeFileClose(fd);
  63. }
  64. });
  65. readBT.setOnClickListener(new OnClickListener() {
  66. @Override
  67. public void onClick(View v) {
  68. // TODO Auto-generated method stub
  69. fd = NativeFileOpen(filename, O_CREAT  | O_RDWR);
  70. System.out.println("fd_read---->" + fd);
  71. buf_read = new byte[buf_write.length];
  72. int ret_read = NativeFileRead(fd, buf_read, buf_write.length);
  73. System.out.println("读出返回结果" + ret_read);
  74. try {
  75. readTV.setText( new String(buf_read, "GB2312") + "");
  76. } catch (UnsupportedEncodingException e) {
  77. // TODO Auto-generated catch block
  78. e.printStackTrace();
  79. }
  80. NativeFileClose(fd);
  81. }
  82. });
  83. seekBT.setOnClickListener(new OnClickListener() {
  84. @Override
  85. public void onClick(View v) {
  86. // TODO Auto-generated method stub
  87. fd = NativeFileOpen(filename, O_CREAT  | O_RDWR);
  88. long Offset=20;
  89. long ret_seek =NativeFileSeek(fd, Offset, SEEK_CUR);
  90. System.out.println("seek返回结果" + ret_seek);
  91. NativeFileClose(fd);
  92. /*    1) 欲将读写位置移到文件开头时:
  93.                          lseek(int fildes,0,SEEK_SET);
  94.                      2) 欲将读写位置移到文件尾时:
  95.                          lseek(int fildes,0,SEEK_END);
  96.                      3) 想要取得目前文件位置时:
  97.                          lseek(int fildes,0,SEEK_CUR);
  98. 返回值:当调用成功时则返回目前的读写位置,也就是距离文件开头多少个字节。若有错误则返回-1,errno 会存放错误代码。
  99. * */
  100. }
  101. });
  102. }
  103. public native int NativeFileOpen(String filename, int flags);
  104. public native int NativeFileRead(int fd, byte[] buf, int sizes);
  105. public native int NativeFileWrite(int fd, byte[] buf, int sizes);
  106. public native long NativeFileSeek(int fd, long Offset, int whence);
  107. //Offset:偏移量,每一读写操作所需要移动的距离,单位是字节的数量,可正可负(向前移,向后移)。
  108. public native int NativeFileClose(int fd);
  109. static {
  110. System.loadLibrary("fs");
  111. }
  112. }

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

  1. <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
  2. <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>


Android的NDK开发(5)————Android JNI层实现文件的read、write与seek操作的更多相关文章

  1. 【转】 Android的NDK开发(1)————Android JNI简介与调用流程

    原文网址:http://blog.csdn.net/conowen/article/details/7521340 ****************************************** ...

  2. Android的NDK开发(1)————Android JNI简介与调用流程

    1.JNI简介 JNI全称为Java Native Interface(Java本地调用).从Java1.1开始,JNI成为java平台的一部分,它允许Java代码和其他语言写的代码(如C&C ...

  3. android的ndk开发简介-android学习之旅(93)

    环境搭建 1.安装ndk 2.安装cygwin (android是基于linux的Framework,运行的本地库是.SO,而不是.dll库,大部分都实在windows下开发,如果是linux就没这个 ...

  4. Android之NDK开发(转)

    Android之NDK开发 一.NDK产生的背景 Android平台从诞生起,就已经支持C.C++开发.众所周知,Android的SDK基于Java实现,这意味着基于Android SDK进行开发的第 ...

  5. Android之NDK开发

    转自:http://www.cnblogs.com/devinzhang/archive/2012/02/29/2373729.html 一.NDK产生的背景 Android平台从诞生起,就已经支持C ...

  6. 【转】Android之NDK开发

    原文网址:http://www.cnblogs.com/devinzhang/archive/2012/02/29/2373729.html 一.NDK产生的背景 Android平台从诞生起,就已经支 ...

  7. android studio ndk 开发入门

    ndk 开发没什么神秘的ndk 说白了就是一个交叉编译的工具链,用它来生成各个CPU架构下的静态或动态链接库,linux 下就是 .a 和 .so 文件.原理就是 java 通过 JNI 和 C.C+ ...

  8. Android之NDK开发(转载)

    http://www.cnblogs.com/devinzhang/archive/2012/02/29/2373729.html 一.NDK产生的背景 Android平台从诞生起,就已经支持C.C+ ...

  9. 【Android】Android Studio NDK 开发

    Android Studio NDK 开发 记录在Android Studio中NDK简单开发的步骤 用到的Android Studio版本为3.5. 配置NDK 下载NDK 一般在SDK下已经有自带 ...

随机推荐

  1. libiconv 支持的编码

    libiconv 支持的编码 php 中的 iconv() 函数常用来作编码转换用.作一些不同编码的动态数据的转换时常遇到一些未知编码的数据,这时 iconv() 支持那些编码转换就很重要. 刚开始, ...

  2. 【例题 7-8 UVA - 10603】Fill

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 三维显然可以缩短为2维. 只要知道a,b瓶中的水量,c瓶中的水量减一下就能得到. 则设dis[a][b]表示a,b瓶中水量为a,b时 ...

  3. Java Web学习总结(12)——使用Session防止表单重复提交

    在平时开发中,如果网速比较慢的情况下,用户提交表单后,发现服务器半天都没有响应,那么用户可能会以为是自己没有提交表单,就会再点击提交按钮重复提交表单,我们在开发中必须防止表单重复提交. 一.表单重复提 ...

  4. 【原创】基于pyautogui进行自动化测试

    前期准备: python3.6 pyautogui pywinauto 以下代码实现内容: 1.打开记事本 2.记事本中输入This is a test 3.保存内容 4.退出进程 import py ...

  5. Redo 非current损坏

    Redo log 文件损坏或丢失,在启动数据库时在alert日志中会有如下错误: ORA-00313: open failed for members of log group 1 of thread ...

  6. HDU 1556 Color the ball【算法的优化】

    /* 解题思路:每次仅仅求解一開始的第一个数字,让第一个数字加一,最后的一个数字的后面一个数减一.我们能够想想,最后加的时候,就是加上前面一个数出现的次数和自己本身出现的次数. 解题人:lingnic ...

  7. 内存问题检查利器——Purify

    内存问题检查利器——Purify 一.           引言 我们都知道软件的测试(在以产品为主的软件公司中叫做QA—Quality Assessment)占了整个软件工程的30% -50%,但有 ...

  8. linux 内核源代码目录结构

    /arch:目录包括了所有和体系结构相关的核心代码.它下面的每一个子目录都代表一种Linux支持的体系结构,例如i386就是Intel CPU及与之相兼容体系结构的子目录.PC机一般都基于此目录. / ...

  9. 再谈ITFriend网站的定位

    在网站开发阶段.内部测试阶段.公开测试阶段,让诸多好友和网友,参与了我们的网站ITFriend的体验和测试.其中,大家非常关心,我们的网站是干什么的.在我们不做任何解释的情况下,有的网站认为ITFri ...

  10. Android layer-list的属性和使用具体解释

    Android layer-list的属性和使用具体解释.layer-list是用来多个图层堆叠显示的,借这个特性能够做一些特别的效果(比方:阴影.以下的效果等),也能够投机取巧. 1.代码片 < ...