/*************************************** **************************************** *************
* Author: conowen @ Dazhong
* E-mail: conowen@hotmail.com
* Http://blog.csdn.net/conowen
* Note: This article is original and only used for learning and communication. For more information, indicate the author and its source.
**************************************** **************************************** ************/
1,
In the android Java layer file read and write operations is very simple, you can refer to the previous written blog: http://blog.csdn.net/conowen/article/details/7296121
To implement file read/write operations on the JNI layer, you need to use the Linux read/write function.
2. Open a file
int open( const char *pathname,int flags, int mode);
Return Value: A file handle (FD) for read and write operations.
Parameters:
Pathname: path string of the opened file. For example
String filename = "/sdcard/test.txt";
Flags: file Opening Method
The flag can be used for the "and" operation, as shown in figure
open(filename, O_CREAT | O_RDWR,mode);
Common flags:
O_rdonly open a file in read-only mode
O_wronly open the file in write-only mode
O_rdwr can open files in read/write mode. The above three flags are mutually exclusive, that is, they cannot be used at the same time, but can be combined with the following flags using the OR (|) operator.
O_creat: if the file to be opened does not exist, the file is automatically created.
If the o_trunc file exists and is opened in writable mode, this flag will refresh the file length to 0, that is, the file content is cleared.
O_append when reading and writing a file, it will start to move from the end of the file, that is, the written data will be appended to the end of the file.
O_nonblock open the file in an unblocking way, that is, whether there is data read or waiting, it will immediately return to the process.
O_sync opens the file in synchronous mode.
O_nofollow if the file indicated by pathname is a symbolic connection, opening the file will fail.
O_directory if the file indicated by the pathname parameter is not a directory, opening the file will fail.
Mode: file storage permission
S_irwxu00700 permission indicates that the object owner has the readable, writable, and executable permissions.
S_irusr, s_iread, and 00400 permissions indicate that the file owner has the readable permission.
S_iwusr or s_iwrite, 00200 permission indicates that the file owner has the write permission.
S_ixusr or s_iexec, 00100 permission indicates that the file owner has executable permission.
S_irwxg 00070 permission indicates that the file user group has the readable, writable, and executable permissions.
S_irgrp 00040 permission indicates that the file user group has the readable permission.
S_iwgrp 00020 permission indicates that the file user group has the write permission.
S_ixgrp 00010 permission indicates that the file user group has executable permissions.
S_irwxo 00007 indicates that other users have the readable, writable, and executable permissions.
S_iroth 00004 permission, which indicates that other users have the readable permission
S_iwoth 00002 permission indicates that other users have the write permission.
S_ixoth 00001 permission indicates that other users have executable permissions.
3. Read operations on files
int read(int fd, unsigned char *buf, int size);
Return Value: returns the actual number of bytes read. If 0 is returned, it indicates that the data has reached the end of the file or is unreadable. In addition, the read/write location of the file will move with the read bytes.
Parameters:
FD: indicates the file handle, which is obtained by the open function.
The Buf: Read () function transfers the file referred to by FD to the memory indicated by the Buf pointer in count bytes.
Size: the number of bytes to read.
4. Write operations
int write (int fd, const unsigned char *buf, int size);
Return Value: If write () is successful, the actual number of bytes written will be returned. -1 is returned when an error occurs.
Parameters:
FD: Same as above
Buf: the content to be written into the file.
Size: the number of bytes to write.
5. Redirect operation
int64_t seek(int fd, int64_t pos, int whence)
Return Value: if the operation succeeds, the current read/write position is returned, that is, the number of bytes starting with the file. If an error occurs, the return value is-1.
Parameters:
FD: Same as above
POs: the relative amount of the jump, which can be positive or negative, indicating the relationship between the front and back of the Relative Position
Whence: The jump direction. The value of whence is as follows:
Int seek_set = 0; // point the read/write position to the file header and then increase the offset displacement. Int seek_cur = 1; // increase the offset displacement at the current read/write position. Int eek_end = 2; // point the read/write position to the end of the file and then increase the offset displacement.
Note: When the size parameter = 0; whence = seek_end;, the returned value is the file size.
6. Disable the operation.
int close(int fd)
7. Simple Example
:
7.1. JNI Code: (jni_onload function is available)
//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";jintJava_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);}jintJava_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);}jintJava_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);}jlongJava_com_conowen_fs_FsActivity_NativeFileSeek(JNIEnv* env, jobject thiz,int fd,jlong Offset,jint whence){return file_seek(fd, Offset, whence);}jintJava_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 __cplusplusextern "C"{#endifint 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 encode (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 ;} // when the Dalvik Virtual Machine loads the C library, the first thing is to call jni_onload () Function 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 balance"); goto end; }__ android_log_print (android_log_info, Tag, "loaded "); result = jni_version_1_4; end: return result ;}
7.2. Android. mk File
LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE := fsLOCAL_SRC_FILES := fs.c jni.c onLoad.cppLOCAL_LDLIBS += -lloginclude $(BUILD_SHARED_LIBRARY)
7.3 Java-Layer Code
/* 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_nonb Lock = 04000; int o_ndelay = o_nonblock; int o_sync = 010000; int o_fsync = o_sync; int o_async = 020000; int seek_set = 0; // point the read/write position to the file header and then increase the offset displacement. Int seek_cur = 1; // increase the offset displacement at the current read/write position. Int eek_end = 2; // point the read/write position to the end of the file and then increase the offset displacement. /** Called when the activity is first created. * // @ overridepublic 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. readt V); writebt. setonclicklistener (New onclicklistener () {@ overridepublic void onclick (view v) {// todo auto-generated method stubfd = 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 ("Write return result" + ret_write); Nativ Efileclose (FD) ;}}); readbt. setonclicklistener (New onclicklistener () {@ overridepublic void onclick (view v) {// todo auto-generated method stubfd = 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 ("read returned results" + ret_read); try {readtv. settext (new string (Buf_read, "gb2312") + "");} catch (unsupportedencodingexception e) {// todo auto-generated catch blocke. printstacktrace () ;}nativefileclose (FD) ;}}); seekbt. setonclicklistener (New onclicklistener () {@ overridepublic void onclick (view v) {// todo auto-generated method stubfd = nativefileopen (filename, o_creat | o_rdwr); long offset = 20; long ret_seek = nativefileseek (FD, offset, seek_cur); system. out. printl N ("seek return result" + ret_seek); nativefileclose (FD);/* 1) to move the read/write position to the beginning of the file: lseek (INT Fildes, 0, seek_set ); 2) to move the read/write position to the end of the file: lseek (INT Fildes, 0, seek_end); 3) to obtain the current file location: lseek (INT Fildes, 0, seek_cur ); return Value: when the call is successful, the current read/write location is returned, that is, the number of bytes from the beginning of the file. If an error occurs,-1 is returned, and errno stores the error code. **/});} 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: Offset, the distance to be moved for each read/write operation. The unit is the number of bytes. It can be positive or negative (forward or backward ). Public native int nativefileclose (int fd); static {system. loadlibrary ("FS ");}}
Remember to add the SD card operation permission to manifest. xml.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>