Android ndk development (5) ---- Android JNI layer implements file read, write, and seek operations

Source: Internet
Author: User
Tags svm

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

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.