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"/>


最新文章

  1. 配置Java SSL 访问网站证书
  2. 移动端重构系列-移动端html页面优化
  3. MySQL操作类(本人自己写的)
  4. 精通 JS正则表达式
  5. javaWeb中一个按钮提交两个表单
  6. 应用框架 ViewPager Tab Fragment SlidingMenu
  7. HTML基础知识笔记(一)
  8. DataFrame创建
  9. #tensorflow入门(1)
  10. 三种方式设置特定设备UWP XAML view
  11. Nginx正向代理与反向代理
  12. Virtualization
  13. 【C++】C++中的流
  14. js------10种循环方法
  15. Logstash解析Json array
  16. SVN windows内修改日志内容(错误解决)
  17. golang语言并发与并行——goroutine和channel的详细理解(一) 转发自https://blog.csdn.net/skh2015java/article/details/60330785
  18. 猎豹CEO傅盛:95%的人碌碌无为,只是不懂这一点!
  19. iOS Sprite Kit教程之使用帮助文档以及调试程序
  20. 执行pig出错Unhandled internal error. Found interface jline.Terminal, but class was expected

热门文章

  1. NOIP2016 天天爱跑步(线段树/桶)
  2. vim学习4
  3. 简单的横向ListView实现(version 4.0)
  4. android屏幕适配方案
  5. JS实现联想自动补齐功能
  6. SpringMVC-如何接收各种参数(普通参数,对象,JSON, URL)
  7. ajax的get请求与编码
  8. [Angular] Protect The Session Id with https and http only
  9. python 深浅拷贝 进阶
  10. android之路Gallery 画廊