/********************************************************************************************
* author:conowen@大钟
* E-mail:conowen@hotmail.com
*
http://blog.csdn.net/conowen
* 注:本文为原创,仅作为学习交流使用,转载请标明作者及出处。

********************************************************************************************/


1、

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

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


2、打开文件

[cpp] view plain copy print ?
  1. intopen(constchar*pathname,intflags,intmode);

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


参数:

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

[java] view plain copy print ?
  1. Stringfilename="/sdcard/test.txt";

flags: 文件打开的方式

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

[java] view plain copy print ?
  1. 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)操作

[cpp] view plain copy print ?
  1. intread(intfd,unsignedchar*buf,intsize);

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

参数

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

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

size:要读取的字节数



4、写入操作

[cpp] view plain copy print ?
  1. intwrite(intfd,constunsignedchar*buf,intsize);

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

参数

fd:同上

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

size:要写入的字节数


5、跳转操作

[cpp] view plain copy print ?
  1. int64_tseek(intfd,int64_tpos,intwhence)

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

参数

fd:同上

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

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

[cpp] view plain copy print ?
  1. intSEEK_SET=0;//将读写位置指向文件头后再增加offset个位移量。
  2. intSEEK_CUR=1;//以目前的读写位置往后增加offset个位移量。
  3. intEEK_END=2;//将读写位置指向文件尾后再增加offset个位移量。

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


6、关闭操作

[cpp] view plain copy print ?
  1. intclose(intfd)


7、简单示例

效果图:





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

[cpp] view plain copy print ?
  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. intfile_open(constchar*filename,intflags)
  8. {
  9. intfd;
  10. fd=open(filename,flags,0666);
  11. if(fd==-1)
  12. return-1;
  13. returnfd;
  14. }
  15. intfile_read(intfd,unsignedchar*buf,intsize)
  16. {
  17. returnread(fd,buf,size);
  18. }
  19. intfile_write(intfd,constunsignedchar*buf,intsize)
  20. {
  21. returnwrite(fd,buf,size);
  22. }
  23. int64_tfile_seek(intfd,int64_tpos,intwhence)
  24. {
  25. if(whence==0x10000){
  26. structstatst;
  27. intret=fstat(fd,&st);
  28. returnret<0?-1:st.st_size;
  29. }
  30. returnlseek(fd,pos,whence);
  31. }
  32. intfile_close(intfd)
  33. {
  34. returnclose(fd);
  35. }

[cpp] view plain copy print ?
  1. //jni.c
  2. #defineTAG"fs_jni"
  3. #include<android/log.h>
  4. #include"jniUtils.h"
  5. staticconstchar*constkClassPathName="com/conowen/fs/FsActivity";
  6. jint
  7. Java_com_conowen_fs_FsActivity_NativeFileOpen(JNIEnv*env,jobjectthiz,jstringfilename,jintflags){
  8. constchar*filename_char=(*env)->GetStringUTFChars(env,filename,NULL);
  9. returnfile_open(filename_char,flags);
  10. }
  11. jint
  12. Java_com_conowen_fs_FsActivity_NativeFileRead(JNIEnv*env,jobjectthiz,intfd,jbyteArraybuf,jintsize){
  13. unsignedchar*buf_char=(char*)((*env)->GetByteArrayElements(env,buf,NULL));
  14. returnfile_read(fd,buf_char,size);
  15. }
  16. jint
  17. Java_com_conowen_fs_FsActivity_NativeFileWrite(JNIEnv*env,jobjectthiz,intfd,jbyteArraybuf,jintsize){
  18. unsignedchar*buf_char=(char*)((*env)->GetByteArrayElements(env,buf,NULL));
  19. returnfile_write(fd,buf_char,size);
  20. }
  21. jlong
  22. Java_com_conowen_fs_FsActivity_NativeFileSeek(JNIEnv*env,jobjectthiz,intfd,jlongOffset,jintwhence){
  23. returnfile_seek(fd,Offset,whence);
  24. }
  25. jint
  26. Java_com_conowen_fs_FsActivity_NativeFileClose(JNIEnv*env,jobjectthiz,intfd){
  27. returnfile_close(fd);
  28. }
  29. /******************************JNIregistration.************************************/
  30. staticJNINativeMethodgMethods[]={
  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. intregister_com_conowen_fs_FsActivity(JNIEnv*env){
  38. returnjniRegisterNativeMethods(env,kClassPathName,gMethods,sizeof(gMethods)/sizeof(gMethods[0]));
  39. }

[cpp] view plain copy print ?
  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. intjniThrowException(JNIEnv*env,constchar*className,constchar*msg);
  11. JNIEnv*getJNIEnv();
  12. intjniRegisterNativeMethods(JNIEnv*env,
  13. constchar*className,
  14. constJNINativeMethod*gMethods,
  15. intnumMethods);
  16. #ifdef__cplusplus
  17. }
  18. #endif
  19. #endif/*_JNI_UTILS_H_*/

[cpp] view plain copy print ?
  1. //onLoad.cpp
  2. #defineTAG"fs_onLoad"
  3. #include<android/log.h>
  4. #include"jniUtils.h"
  5. extern"C"{
  6. externintregister_com_conowen_fs_FsActivity(JNIEnv*env);
  7. }
  8. staticJavaVM*sVm;
  9. /*
  10. *Throwanexceptionwiththespecifiedclassandanoptionalmessage.
  11. */
  12. intjniThrowException(JNIEnv*env,constchar*className,constchar*msg){
  13. jclassexceptionClass=env->FindClass(className);
  14. if(exceptionClass==NULL){
  15. __android_log_print(ANDROID_LOG_ERROR,
  16. TAG,
  17. "Unabletofindexceptionclass%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. "Failedthrowing'%s''%s'",
  25. className,msg);
  26. }
  27. return0;
  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. "FailedtoobtainJNIEnv");
  35. returnNULL;
  36. }
  37. returnenv;
  38. }
  39. /*
  40. *RegisternativeJNI-callablemethods.
  41. *
  42. *"className"lookslike"java/lang/String".
  43. */
  44. intjniRegisterNativeMethods(JNIEnv*env,
  45. constchar*className,
  46. constJNINativeMethod*gMethods,
  47. intnumMethods)
  48. {
  49. jclassclazz;
  50. __android_log_print(ANDROID_LOG_INFO,TAG,"Registering%snatives\n",className);
  51. clazz=env->FindClass(className);
  52. if(clazz==NULL){
  53. __android_log_print(ANDROID_LOG_ERROR,TAG,"Nativeregistrationunabletofindclass'%s'\n",className);
  54. return-1;
  55. }
  56. if(env->RegisterNatives(clazz,gMethods,numMethods)<0){
  57. __android_log_print(ANDROID_LOG_ERROR,TAG,"RegisterNativesfailedfor'%s'\n",className);
  58. return-1;
  59. }
  60. return0;
  61. }
  62. //Dalvik虚拟机加载C库时,第一件事是调用JNI_OnLoad()函数
  63. jintJNI_OnLoad(JavaVM*vm,void*reserved){
  64. JNIEnv*env=NULL;
  65. jintresult=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,"GetEnvfailed!");
  69. returnresult;
  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'tloadregister_com_conowen_fs_FsActivity");
  74. gotoend;
  75. }
  76. __android_log_print(ANDROID_LOG_INFO,TAG,"loaded");
  77. result=JNI_VERSION_1_4;
  78. end:
  79. returnresult;
  80. }

7.2、Android.mk文件


[cpp] view plain copy print ?
  1. LOCAL_PATH:=$(callmy-dir)
  2. include$(CLEAR_VARS)
  3. LOCAL_MODULE:=fs
  4. LOCAL_SRC_FILES:=fs.cjni.conLoad.cpp
  5. LOCAL_LDLIBS+=-llog
  6. include$(BUILD_SHARED_LIBRARY)


7.3、java层代码

[java] view plain copy print ?
  1. /*author:conowen
  2. *data:2012.5.1
  3. *e-mail:conowen@hotmail.com
  4. */
  5. packagecom.conowen.fs;
  6. importjava.io.UnsupportedEncodingException;
  7. importandroid.app.Activity;
  8. importandroid.os.Bundle;
  9. importandroid.view.View;
  10. importandroid.view.View.OnClickListener;
  11. importandroid.widget.Button;
  12. importandroid.widget.EditText;
  13. importandroid.widget.TextView;
  14. publicclassFsActivityextendsActivity{
  15. Stringfilename="/sdcard/test.txt";
  16. EditTextwritestrET;
  17. ButtonwriteBT;
  18. ButtonreadBT;
  19. ButtonseekBT;
  20. TextViewreadTV;
  21. StringwriteStr;
  22. byte[]buf_write;
  23. byte[]buf_read;
  24. intfd;
  25. intO_ACCMODE=0003;
  26. intO_RDONLY=00;
  27. intO_WRONLY=01;
  28. intO_RDWR=02;
  29. intO_CREAT=0100;/*notfcntl*/
  30. intO_EXCL=0200;/*notfcntl*/
  31. intO_NOCTTY=0400;/*notfcntl*/
  32. intO_TRUNC=01000;/*notfcntl*/
  33. intO_APPEND=02000;
  34. intO_NONBLOCK=04000;
  35. intO_NDELAY=O_NONBLOCK;
  36. intO_SYNC=010000;
  37. intO_FSYNC=O_SYNC;
  38. intO_ASYNC=020000;
  39. intSEEK_SET=0;//将读写位置指向文件头后再增加offset个位移量。
  40. intSEEK_CUR=1;//以目前的读写位置往后增加offset个位移量。
  41. intEEK_END=2;//将读写位置指向文件尾后再增加offset个位移量。
  42. /**Calledwhentheactivityisfirstcreated.*/
  43. @Override
  44. publicvoidonCreate(BundlesavedInstanceState){
  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(newOnClickListener(){
  53. @Override
  54. publicvoidonClick(Viewv){
  55. //TODOAuto-generatedmethodstub
  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. intret_write=NativeFileWrite(fd,buf_write,buf_write.length);
  61. System.out.println("写入返回结果"+ret_write);
  62. NativeFileClose(fd);
  63. }
  64. });
  65. readBT.setOnClickListener(newOnClickListener(){
  66. @Override
  67. publicvoidonClick(Viewv){
  68. //TODOAuto-generatedmethodstub
  69. fd=NativeFileOpen(filename,O_CREAT|O_RDWR);
  70. System.out.println("fd_read---->"+fd);
  71. buf_read=newbyte[buf_write.length];
  72. intret_read=NativeFileRead(fd,buf_read,buf_write.length);
  73. System.out.println("读出返回结果"+ret_read);
  74. try{
  75. readTV.setText(newString(buf_read,"GB2312")+"");
  76. }catch(UnsupportedEncodingExceptione){
  77. //TODOAuto-generatedcatchblock
  78. e.printStackTrace();
  79. }
  80. NativeFileClose(fd);
  81. }
  82. });
  83. seekBT.setOnClickListener(newOnClickListener(){
  84. @Override
  85. publicvoidonClick(Viewv){
  86. //TODOAuto-generatedmethodstub
  87. fd=NativeFileOpen(filename,O_CREAT|O_RDWR);
  88. longOffset=20;
  89. longret_seek=NativeFileSeek(fd,Offset,SEEK_CUR);
  90. System.out.println("seek返回结果"+ret_seek);
  91. NativeFileClose(fd);
  92. /*  1)欲将读写位置移到文件开头时:
  93.   lseek(intfildes,0,SEEK_SET);
  94.   2)欲将读写位置移到文件尾时:
  95.   lseek(intfildes,0,SEEK_END);
  96.   3)想要取得目前文件位置时:
  97.   lseek(intfildes,0,SEEK_CUR);
  98. 返回值:当调用成功时则返回目前的读写位置,也就是距离文件开头多少个字节。若有错误则返回-1,errno会存放错误代码。
  99. **/
  100. }
  101. });
  102. }
  103. publicnativeintNativeFileOpen(Stringfilename,intflags);
  104. publicnativeintNativeFileRead(intfd,byte[]buf,intsizes);
  105. publicnativeintNativeFileWrite(intfd,byte[]buf,intsizes);
  106. publicnativelongNativeFileSeek(intfd,longOffset,intwhence);
  107. //Offset:偏移量,每一读写操作所需要移动的距离,单位是字节的数量,可正可负(向前移,向后移)。
  108. publicnativeintNativeFileClose(intfd);
  109. static{
  110. System.loadLibrary("fs");
  111. }
  112. }


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

[html] view plain copy print ?
  1. <uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
  2. <uses-permissionandroid:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>

更多相关文章

  1. NPM 和webpack 的基础使用
  2. 【阿里云镜像】使用阿里巴巴DNS镜像源——DNS配置教程
  3. windows下搭建cocos2dx Android开发环境
  4. Android(安卓)文件操作
  5. android 判断联网类型
  6. Android手机拍照和手机相册选取图片的工具类ImageUtils
  7. android之File
  8. Android(安卓)Ant打包及其环境变量配置
  9. Android(安卓)时区的修改增删,如何在菜单里增加一个没有的时区

随机推荐

  1. Android 编译流程解析01-AppPlugin初始化
  2. Android中PackageManager学习笔记(3)-Pac
  3. Android本地数据搜索实现
  4. 关于Android Studio关闭模拟器死机解决方
  5. 监听电话状态
  6. android WebView 应用内点击超链接不调用
  7. 《Android.Programming.Pushing.the.Limi
  8. Android 自定义设置文本字体间间距
  9. Android下的junit 单元测试
  10. Android 上下文菜单