您的位置:首页 > 移动开发 > Android开发

Android - jni - 读取文件操作

2020-08-04 11:51 881 查看

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

1. 加权限

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

<!--添加读写权限-->
<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 <jni.h>
#include <string>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#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);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: