Android - jni - 读取文件操作

创建一个 Native C++工程的项目

1. 加权限

具体看:Android 6.0 - 申请动态权限

Android - jni - 读取文件操作_第1张图片

	<!--添加读写权限-->
	<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

在这里插入图片描述

2. Java - jni

	static {
        	System.loadLibrary("native-lib");
    	}

   /*
    * 文件路径
    * */
    public native String getFromC(String path);

    /*
    * 打开文件
    * */
    public native int NativeFileOpen(String filename, int flags);

    /*
    * 读取文件
    * */
    public native int NativeFileRead(int fd, byte[] buf, int sizes);

    /*
    * 指针指向0,否则会在当前位置,读不出写入数据
    * */
    public native long NativeFileSeek(int fd, long Offset, int whence);

    /*
    * 关闭文件
    * */
    public native int NativeFileClose(int fd);

在这里插入图片描述

3. Native - lib

//头文件
#include 
#include 
#include 
#include 
#include 
#include "android/log.h"
#define  LOG    "JNILOG"
#define  LOGD(...)  __android_log_print(ANDROID_LOG_DEBUG,LOG,__VA_ARGS__)
//打开文件
int file_open(const char *filename,int flags)
{
    int fd;
/* 具体可看(https://blog.csdn.net/simongyley/article/details/8330636)
 *
 *  参数1:指欲打开的文件路径字符串
    参数2:所使用的标记:
        O_RDONLY 以只读方式打开文件
        O_WRONLY 以只写方式打开文件
        O_RDWR   以可读写方式打开文件。
            (上述三种旗标是互斥的,也就是不可同时使用,但可与下列的旗标利用OR(|)运算符组合。)
        O_CREAT 若欲打开的文件不存在则自动建立该文件。
    参数3:权限
        S_IRWXU00700 权限,代表该文件所有者具有可读、可写及可执行的权限。
        S_IRUSR 或S_IREAD,00400权限,代表该文件所有者具有可读取的权限。
        S_IWUSR 或S_IWRITE,00200 权限,代表该文件所有者具有可写入的权限。
        S_IXUSR 或S_IEXEC,00100 权限,代表该文件所有者具有可执行的权限。
        S_IRWXG 00070权限,代表该文件用户组具有可读、可写及可执行的权限。
    */
    fd = open(filename, flags, 0666);

    //若所有欲核查的权限都通过了检查则返回 0值,表示成功,
    //只要有一个权限被禁止则返回-1。
    if (fd == -1){
        return -1;
    }
    return fd;
}

//读取文件
int file_read(int fd, unsigned char *buf, int size)
{
    return read(fd, buf, size);
}

//指针指向0,否则会在当前位置,读不出写入数据
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中 jstring转换成 char* 的函数
char* jstringTostring(JNIEnv* env,jstring jstr)
{
    char* rtn =NULL;
    jclass clsstring = env->FindClass("java/lang/String");
    //参数1:java类对象    参数2:方法名    参数3:该参数的签名
    jmethodID mid = env->GetMethodID(
            clsstring,"getBytes","(Ljava/lang/String;)[B");
    jstring strencode = env->NewStringUTF("utf-8");
    jbyteArray barr=(jbyteArray)env->CallObjectMethod(jstr, mid, strencode);
    jbyte* ba =env->GetByteArrayElements(barr, JNI_FALSE);
    jsize alen =env->GetArrayLength(barr);
    if (alen > 0)
    {
        rtn = (char*)malloc(alen+ 1);
        memcpy(rtn, ba, alen);
        rtn[alen] = 0;
    }
    env->ReleaseByteArrayElements(barr, ba, 0);
    return rtn;
}
//文件路径
extern "C"
JNIEXPORT jstring JNICALL
Java_com_example_jnitext_1open_1write_1read_MainActivity_getFromC
(JNIEnv *env, jobject jobj,jstring jstr) {
    // TODO: implement getFromC()
    char* javaPath = jstringTostring(env,jstr);
    file_open(javaPath, O_RDWR);
    return (env)->NewStringUTF(javaPath);
};


//转换
extern "C"
JNIEXPORT jint JNICALL
Java_com_example_jnitext_1open_1write_1read_MainActivity_NativeFileOpen
(JNIEnv *env, jobject jobj,jstring filename,jint flags) {
    // TODO: implement NativeFileOpen()
    char* javaPath = jstringTostring(env, filename);
    return file_open(javaPath, flags);
}


//读取文件
extern "C"
JNIEXPORT jint JNICALL
Java_com_example_jnitext_1open_1write_1read_MainActivity_NativeFileRead
(JNIEnv *env, jobject jobj,jint fd, jbyteArray buf,jint sizes) {
    // TODO: implement NativeFileRead()
    unsigned char* buf_char = (unsigned char*)
            (env)->GetByteArrayElements(buf,NULL);
    return file_read(fd,buf_char,sizes);
}


//指针指向0,否则会在当前位置,读不出写入数据
extern "C"
JNIEXPORT jlong JNICALL
Java_com_example_jnitext_1open_1write_1read_MainActivity_NativeFileSeek(JNIEnv *env, jobject thiz,
        jint fd, jlong offset,jint whence) {
    // TODO: implement NativeFileSeek()
    return file_seek(fd, offset,  whence);
}


//关闭文件
extern "C"
JNIEXPORT jint JNICALL
Java_com_example_jnitext_1open_1write_1read_MainActivity_NativeFileClose
        (JNIEnv *env, jobject jobj,jint fd) {
    // TODO: implement NativeFileClose()
    return file_close(fd);
}

在这里插入图片描述

4. Java - main

    byte[] buf_wirte = new byte[1024];
    byte[] buf_read = new byte[1024];
    int O_RDWR = 02; //以可读写方式打开文件
    int O_CREAT = 0100; //若欲打开的文件不存在,则自动建立该文件
    //文件路径
    String path = "/storage/emulated/0/1/";
    String fromC = getFromC(path + "key.txt");


  @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
		//添加权限
        verifyStoragePermissions(this);
        TextView tv = findViewById(R.id.tv);

		//打开文件
        int fd = NativeFileOpen(fromC, O_CREAT | O_RDWR);
		//指针指向0
        long ret_seek =NativeFileSeek(fd, 0, SEEK_SET);
		//读取文件
        buf_read = new byte[buf_wirte.length];
        int ret_read = NativeFileRead(fd,buf_read,buf_wirte.length);
        if (ret_read == 0){
            System.out.println("文件内容为空");
        }else {
            try {
                tv.setText(new String(buf_read, "GB2312") + " ");
            }  catch (UnsupportedEncodingException e){
                e.printStackTrace();
            }
        }
        
        //关闭
        NativeFileClose(fd);
    }

你可能感兴趣的:(Android,Studio,jni,android,java)