`
iaiai
  • 浏览: 2204118 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

[转]Android JNI层实现文件的read、write与seek操作

 
阅读更多
1、
          在Android的java层实现文件的读写操作是非常简单的
          在JNI层实现文件的读写操作的话,就要使用到linux的读写函数了。

2、打开文件
int open( const char *pathname,int flags, int mode);

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

参数:
pathname: 打开的文件所在路径字符串。如
String filename = "/sdcard/test.txt";

flags: 文件打开的方式
flag之间可以作“与”运算,如
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)操作
int read(int fd, unsigned char *buf, int size);

返回值:返回实际读取到的字节数,如果返回0,表示已到达文件尾或是无可读取的数据,此外文件读写位置会随读取到的字节移动。
参数:
fd:表示文件句柄,是由open函数得到
buf:read()函数会把fd 所指的文件传送count个字节到buf指针所指的内存中
size:要读取的字节数


4、写入操作
int write (int fd, const unsigned char *buf, int size);

返回值 :如果成功write(),就会返回实际写入的字节数。当有错误发生时则返回-1
参数:
fd:同上
buf:将要写入到文件里面的内容。
size:要写入的字节数

5、跳转操作
int64_t seek(int fd, int64_t pos, int whence)

返回值:成功时则返回目前的读写位置,也就是距离文件开头多少个字节,若有错误则返回-1。
参数:
fd:同上
pos:跳转的相对量,可正可负,表示相对位置的前后关系
whence:跳转的方向,whence取值如下所示
int SEEK_SET   =        0;//将读写位置指向文件头后再增加offset个位移量。  
int SEEK_CUR   =        1;//以目前的读写位置往后增加offset个位移量。  
int EEK_END    =        2;//将读写位置指向文件尾后再增加offset个位移量。

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

6、关闭操作
int close(int fd)

7、简单示例
效果图:


7.1、JNI代码:(有JNI_onLoad函数)
//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";  

jint Java_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);  
}  
jint Java_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);  
}  
  
jint Java_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);  
}  
  
jlong Java_com_conowen_fs_FsActivity_NativeFileSeek(JNIEnv* env, jobject thiz,int fd,jlong Offset,jint whence){
    return file_seek(fd, Offset,  whence);  
}  
  
jint Java_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 __cplusplus  
extern "C" {  
#endif  
  
int 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 jniRegisterNativeMethods(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;  
}  
//Dalvik虚拟机加载C库时,第一件事是调用JNI_OnLoad()函数  
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 register_com_conowen_fs_FsActivity");  
        goto end;  
    }  
  
    __android_log_print(ANDROID_LOG_INFO, TAG, "loaded");  
  
    result = JNI_VERSION_1_4;  
  
end:  
    return result;  
}

7.2、Android.mk文件
LOCAL_PATH := $(call my-dir)  
  
include $(CLEAR_VARS)  
  
LOCAL_MODULE    := fs  
LOCAL_SRC_FILES := fs.c jni.c onLoad.cpp  
LOCAL_LDLIBS  += -llog  
  
include $(BUILD_SHARED_LIBRARY)

7.3、java层代码
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_NONBLOCK =   04000;  
    int O_NDELAY   = O_NONBLOCK;  
    int O_SYNC     =  010000;  
    int O_FSYNC    =  O_SYNC;  
    int O_ASYNC    =  020000;  
      
    int SEEK_SET   =        0;//将读写位置指向文件头后再增加offset个位移量。  
    int SEEK_CUR   =        1;//以目前的读写位置往后增加offset个位移量。  
    int EEK_END    =        2;//将读写位置指向文件尾后再增加offset个位移量。   
      
    /** Called when the activity is first created. */  
    @Override  
    public 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.readTV);  
        writeBT.setOnClickListener(new OnClickListener() {  
  
            @Override  
            public void onClick(View v) {  
                // TODO Auto-generated method stub  
                fd = 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("写入返回结果" + ret_write);  
                NativeFileClose(fd);  
  
            }  
        });  
        readBT.setOnClickListener(new OnClickListener() {  
  
            @Override  
            public void onClick(View v) {  
                // TODO Auto-generated method stub  
                fd = 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("读出返回结果" + ret_read);  
                try {  
                    readTV.setText( new String(buf_read, "GB2312") + "");  
                } catch (UnsupportedEncodingException e) {  
                    // TODO Auto-generated catch block  
                    e.printStackTrace();  
                }  
                NativeFileClose(fd);  
            }  
        });  
        seekBT.setOnClickListener(new OnClickListener() {  
  
            @Override  
            public void onClick(View v) {  
                // TODO Auto-generated method stub  
                fd = NativeFileOpen(filename, O_CREAT  | O_RDWR);  
                long Offset=20;  
                long ret_seek =NativeFileSeek(fd, Offset, SEEK_CUR);  
              
                System.out.println("seek返回结果" + ret_seek);  
                  
                NativeFileClose(fd);  
                /*    1) 欲将读写位置移到文件开头时: 
                         lseek(int fildes,0,SEEK_SET); 
                     2) 欲将读写位置移到文件尾时: 
                         lseek(int fildes,0,SEEK_END); 
                     3) 想要取得目前文件位置时: 
                         lseek(int fildes,0,SEEK_CUR); 
                返回值:当调用成功时则返回目前的读写位置,也就是距离文件开头多少个字节。若有错误则返回-1,errno 会存放错误代码。 
                 * */  
            }  
        });  
  
    }  
  
    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:偏移量,每一读写操作所需要移动的距离,单位是字节的数量,可正可负(向前移,向后移)。  
  
    public native int NativeFileClose(int fd);  
  
    static {  
        System.loadLibrary("fs");  
    }  
}

最后记得在manifest.xml里面加上SD卡操作权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>  
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>


android职业交流QQ 群,有兴趣的可以一起来多搞搞技术、职业交流,互相学习、提高,互通好的职业信息,群号:104286694
  • 大小: 80.9 KB
  • 大小: 67.5 KB
分享到:
评论

相关推荐

    Android中JNI实现AES加密源代码

    综上所述,"Android中JNI实现AES加密源代码"涉及的知识点包括Android JNI的使用、AES加密算法的实现、NDK开发环境的配置、C/C++与Java的交互,以及数据安全和性能优化。通过这样的实现,开发者可以在Android应用中...

    Android JNI调用-文件操作

    文件操作在Android的JNI层可以更直接地利用C/C++库,如标准库或者第三方库,如Boost、Apache Commons IO等,这在处理大量数据或执行高效I/O操作时特别有用。但需要注意的是,由于跨进程和线程同步的问题,直接在JNI...

    Android JNI层实现扫描sd卡mp3文件

    通过以上步骤,我们可以实现一个在Android JNI层扫描SD卡并查找MP3文件的功能。这个过程中涉及到了Android的Java-Native交互、文件操作、权限管理以及C/C++编程等多个技术点,是Android开发中的一个重要实践。

    android jni 加密demo

    通过这个JNI加密demo,开发者可以实现在Android应用中直接调用C/C++代码进行加密和解密操作,这在处理敏感数据、提高性能或者利用第三方加密库时非常有用。然而,需要注意的是,直接操作底层库可能存在安全风险,...

    Android JNI 用C函数写本地库读写文件,底层调用小例子

    总结起来,这个示例展示了如何在Android中使用JNI和C语言实现文件的读写操作。通过这种方式,开发者可以充分利用C语言的性能优势,同时保持Java的易用性和跨平台性。在实际项目中,这可能用于处理大量数据、加密解密...

    Android下AES加密算法的JNI实现(包含SO文件)

    本资源提供了一个具体的实例,即在Android环境下使用JNI实现AES(Advanced Encryption Standard)加密算法,并包含了编译生成的SO(Shared Object)库文件,方便开发者直接集成到项目中。 AES是一种广泛使用的对称...

    serial_jni_largestgle_Androidjni_Android串口操作JNI代码_android_

    `serial_jni_largestgle_Androidjni_Android串口操作JNI代码_android_`这个项目就是关于如何使用JNI来实现Android设备的串口读写的示例。 首先,我们需要了解JNI的概念。JNI是Java平台提供的一种接口,允许Java代码...

    android jni使用curl进行http请求和文件下载

    在Android开发中,JNI(Java Native Interface)是一种技术,允许Java代码和其他编程语言(如C++)进行交互。JNI在很多场景下都很有用,比如优化性能、调用系统底层库或者像本例中那样,利用C/C++库来实现特定功能。...

    android jni 屏幕截图 NativeScreenCapture

    在Android开发中,JNI(Java Native Interface)是一个关键的组件,它允许Java代码与本地(C/C++)代码进行交互。本项目“android jni 屏幕截图 NativeScreenCapture”专注于利用JNI技术来实现Android设备的屏幕截图...

    AndroidJNI技术实现

    在深入探讨Android JNI技术实现的过程中,我们首先需要理解JNI(Java Native Interface)的基本概念与作用。JNI是一种标准的Java平台接口,它允许Java代码与其他语言(如C、C++)编写的本地代码进行交互,这对于...

    android jni获取 Mac地址

    接下来,我们创建一个`JniMacAddress.cpp`文件,这个文件会包含JNI函数的具体实现: ```cpp #include &lt;jni.h&gt; #include &lt;android/log.h&gt; #include extern "C" JNIEXPORT jstring JNICALL Java_...

    Callback_Androidjni_AndoidJNI层到Java层的调用_android_android回调_

    本示例着重探讨如何从Android JNI层回调到Java层,这对于实现性能优化、利用现有C/C++库或处理特定硬件功能时非常有用。 首先,我们来理解JNI的基本概念。JNI是Java平台的一部分,它提供了一个框架,让Java代码能够...

    android jni使用libzip读取压缩文件

    在Android环境中,通过JNI调用libzip库可以实现原生层对ZIP文件的操作,这在处理大量数据或者需要高效读取压缩文件的场景下非常有用。 首先,你需要在Android项目的jniLibs目录下添加libzip库的.so文件,确保它们...

    androidjni编程,java和c层的互相通信传递数据

    Android JNI(Java Native Interface)编程是Android开发中的一个重要部分,它允许Java代码和其他语言(如C/C++)编写的代码进行交互。JNI在Android平台上扮演着桥梁的角色,使得开发者能够利用C/C++的强大性能和...

    android下一个jni方式实现的音频播放

    本示例着重于使用JNI在Android系统中实现音频的播放功能,这是一个深入理解Android NDK(Native Development Kit)和音频处理的好教材。 首先,我们需要了解JNI的基本原理。JNI是Java平台的一部分,它提供了在Java...

    androidjni实现本地加解密数据,使用C++语言编写,基于openssl实现 集成RSAAES3DESBASE64MD5

    本项目主要探讨了如何使用C++语言通过JNI(Java Native Interface)与Android应用交互,实现基于OpenSSL库的加解密算法,包括RSA、AES、3DES、BASE64和MD5。以下是关于这些技术的详细解释: 1. **JNI(Java Native ...

    Android JNI demo

    Android JNI(Java Native Interface)是Android开发中的一个重要概念,它为Java代码提供了与本地C/C++代码交互的能力。JNI在Android应用开发中的作用主要体现在以下几个方面: 1. 性能优化:对于计算密集型任务...

    android JNI运行NDK编译成的可执行文件

    在Android开发中,JNI(Java Native Interface)是一个关键的组件,它允许Java代码与本地C/C++代码进行交互。JNI的使用通常涉及到Android NDK(Native Development Kit),这是一个用于构建原生库的工具集,可以将C/...

    android jni调用demo

    Android的JNI(Java Native Interface)调用是Android应用开发中的一个重要技术,允许Java代码与本地C/C++代码交互。在Android NDK(Native Development Kit)的帮助下,开发者可以利用C/C++的强大性能处理复杂的...

    Android-ndk-jni AES加解密 C++

    本知识点主要聚焦于如何在Android NDK(Native Development Kit)环境下,通过JNI(Java Native Interface)来实现AES(Advanced Encryption Standard)加解密。以下是关于这一主题的详细阐述。 **AES加解密简介** ...

Global site tag (gtag.js) - Google Analytics