JNI获取assets文件夹内的文件地址
0、前言
在深度学习的JNI时,需要把模型文件放到assets里,加载时,却不知道模型的目录地址,报错:该文件未找到.
因为assert文件夹 只是Android系统管理,加载模型需要从系统文件中读取.所以需要把assert的文件写到系统文件中.
1、NCNN
ncnn已经集成了AAssetManager,在模型加载时,传入AAssetManager 参数,他就会实现自动写入系统,并读取相应目录地址,JNI例子如下:
#include <jni.h>
#include <string>
#include <iostream>
#include <net.h>
#include <android/asset_manager_jni.h> //AAssetManager需要
//模型文件mnet.25-opt.param、mnet.25-opt.bin放在asserts中
static ncnn::Net retinaface;
extern "C" JNIEXPORT jboolean JNICALL
Java_com_example_retainfacencnn_RetinaFace_Init(JNIEnv *env, jobject thiz, jobject assetManager) {AAssetManager *mgr = AAssetManager_fromJava(env, assetManager);int ret = retinaface.load_param(mgr, "mnet.25-opt.param");ret = retinaface.load_model(mgr, "mnet.25-opt.bin");
AAssetManager其他功能:
AAssetManager *mgr = AAssetManager_fromJava(env, assetManager)
//打开assert文件夹
AAssetDir *dir = AAssetManager_openDir(mgr,"");
//打开assert下的子文件夹part1
AAssetDir *dir = AAssetManager_openDir(mgr,"part1");
//获取文件名
const char *file = nullptr;
file =AAssetDir_getNextFileName(dir));
//打开文件
AAsset* asset = AAssetManager_open(AAssetManager* mgr, const char* filename, int mode);//mode 可以为AASSET_MODE_STREAMING
//获取文件长度 获取文件长度,如果文件不是很大可以直接用malloc分配空间使用AAsset_read进度文件内容读取。
int len = AAsset_getLength(asset);
//读取文件
unsigned char *buf = (unsigned char *) malloc(sizeof(unsigned char) * len);
AAsset_read(asset, buf, static_cast<size_t>(len));
//关闭文件
AAsset_close(asset);
//关闭文件夹
AAssetDir_close(dir);
2、手动获取地址
CPP无法直接获取文件目录地址,需要在JAVA中对文件进行拷贝到系统中,获取它的绝对地址,传给JNI
2.1 JAVA类方法
2.1.1 方法1
package com.ylz.seetaface;
import java.io.FileNotFoundException; //异常
import android.content.res.AssetManager;
import java.io.BufferedInputStream;
import java.io.FileOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);String cstapath = getPath("face_detector.csta", this); //调用获取文件地址方法boolean ret_init = seetaFace.loadModel(cstapath) //加载模型...(其他代码略)...//获取文件地址方法private static String getPath(String file, Context context) {AssetManager assetManager = context.getAssets();BufferedInputStream inputStream = null;try {// Read data from assets.inputStream = new BufferedInputStream(assetManager.open(file)); //打开文件放入输入流中byte[] data = new byte[inputStream.available()]; //输入流信息放入data中inputStream.read(data); //输入流读取datainputStream.close(); //输入流关闭// Create copy file in storage.File outFile = new File(context.getFilesDir(), file); //新文件(夹)创建,应用文件目录FileOutputStream os = new FileOutputStream(outFile); //输出流os.write(data); //写入数据.即完成了拷贝os.close(); //关闭// Return a path to file which may be read in common way.Log.d("filePath:",outFile.getAbsolutePath());return outFile.getAbsolutePath(); //得到新文件的绝对地址} catch (IOException ex) {Log.i("打开失败", "无法打开此文件");}return "";}}
}
2.1.2 方法2
package com.ylz.seetaface;
import java.io.FileNotFoundException; //异常
import android.content.res.AssetManager; //获取getAssets()
import java.io.BufferedInputStream;
import java.io.FileOutputStream;
import java.io.File; //获取getCacheDir()
import java.io.IOException;
import java.io.InputStream;public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);boolean mkdir_model = copyAssetAndWrite("face_detector.csta");if(mkdir_model==true){File dataFile=new File(getCacheDir(),"face_detector.csta");String cstapath=dataFile.getAbsolutePath();Log.e("文件地址为:", cstapath);boolean ret_init = seetaFace.loadModel(cstapath);}...(其他代码略)...//获取文件地址方法 private boolean copyAssetAndWrite(String fileName){try {File cacheDir=getCacheDir(); //获取文件夹 缓冲目录if (!cacheDir.exists()){cacheDir.mkdirs();}File outFile =new File(cacheDir,fileName); //新建文件if (!outFile.exists()){boolean res=outFile.createNewFile(); //如果不存在,则新建if (!res){return false; //新建失败}}else {if (outFile.length()>10){//表示已经写入一次return true;}}InputStream is=getAssets().open(fileName); //输入流打开文件FileOutputStream fos = new FileOutputStream(outFile); //新文件(这时候还是空)放入输出流byte[] buffer = new byte[1024];int byteCount;while ((byteCount = is.read(buffer)) != -1) {fos.write(buffer, 0, byteCount); //输出流写入数据}fos.flush();is.close(); //输入流关闭fos.close(); //输出流关闭return true;} catch (IOException e) {e.printStackTrace();}return false;}
2.2 JNI中方法
#include <jni.h>
#include <string>
#include <seeta/Common/Struct.h>static Seetaface seetaNet;extern "C" JNIEXPORT jboolean
Java_com_ylz_seetaface_SeetaFace_loadModel(JNIEnv *env,jobject thiz,jstring cstapath) {//模型初始化const char *modelpath = env->GetStringUTFChars(cstapath, 0); //jstring转char*LOGI("model_path:%s",modelpath);seetaNet.Init(model_path);env->ReleaseStringUTFChars(cstapath, modelpath);
2.3 获取的地址
两种方法获取的地址区别:
方法一获取的文件地址为:/data/user/0/com.ylz.seetaface/files/face_detector.csta
com.ylz.seetaface : 应用创建的JAVA类名
files: 利用getFilesDir(),得到的是应用文件目录
方法二获取的文件地址为:/data/user/0/com.ylz.seetaface/cache/face_detector.csta
cache: 利用getCacheDir() 得到的是应用缓存目录
区别在于子文件夹名,方法1为files, 方法2为cache
只需修改代码中的getFilesDir()或者getCacheDir() 即可保持一致
各自获取子文件夹目录地址转string:
getCacheDir().getPath();
getFilesDir().getPath();
参考1(Android JNI实现图片处理和coco-mobilenet模型加载(OpenCV) - 简书) Android JNI实现图片处理和coco-mobilenet模型加载(OpenCV)
参考2(Android获取assets文件路径_dreamsever的专栏-CSDN博客_android获取assets文件路径) Android获取assets文件路径
参考3([Android]JNI进阶1-读取本地文件夹 - 简书) [Android]JNI进阶1-读取本地文件夹
[参考4] (10条消息) Android存储路径获取,getCacheDir()、getFilesDir()、getExternalFilesDir()、getExternalCacheDir()的区别_e电动小马达e的博客-CSDN博客
JNI获取assets文件夹内的文件地址相关推荐
- Android 获取assets文件夹中音频文件的引用,并播放音乐
//本地app中的assets文件夹有music_1.mp3的文件,那么怎么获取文件引用,并直接播放这个文件呢 private void playMusic(boolean play) { ...
- vue获取本地文件夹内所有图片
<script> const path = require("path"); //读取文件的路径 是否遍历文件的子目录 匹配文件正则表达式 const files = ...
- php过去文件夹总数,用php获取文件夹内文件的数量
欢迎进入Linux社区论坛,与200万技术人员互动交流 >>进入 用php获取指定文件夹内文件的数量: 用PHP读取一个文件夹内有多少个文件,例如有一个Picture文件夹,里面有200张 ...
- Python 获取当前文件夹所有文件名并写入到excel文件中
在工作中,有时候,我们需要整理文件夹中的所有文件名称,并罗列在一张表格中.天哪,我的文件夹中有上千个文件,要一个个的复制粘贴吗?太麻烦了吧?今天,我们用Python来解决这个问题. 1. 使用方法: ...
- Android基础篇 访问Assets文件夹里面的资源【文本、图片、音频、字体包】
一.创建Assest文件夹 直接把资源复制粘贴到该文件夹下 (1)获取Assets文件夹的管理类 AssetManager assets = getAssets(); (2)遍历文件夹下的资源列表 S ...
- assets android 作用,Android assets文件夹之位置放置和作用
Android 的assets文件夹的放置位置,Eclipse创建项目时就生成了的,Android Studio则不太一样,AS可以包含几种方式, 1:可以在build.gradle文件下配置,加如下 ...
- SFTP获取文件夹内的文件名,文件大小,文件修改时间
SFTP获取文件夹内的文件名,文件大小,文件修改时间 使用SFTP协议获取服务上的指定路径的文件夹下的所有文件名,文件大小,文件的修改时时间等. 工具类 import java.io.File; im ...
- 使用python将歌词文件(.lrc文件)转换成字典及遍历获取文件夹内所有lrc文件并以lrc格式显示出来
import os class Get_lrcs(): #将lrc文件转换成字典def lrc_to_dict(file_path:str,filenmae:str): #需要传入的参数:文件路径,文 ...
- Java获取文件大小,文件夹内文件个数的工具类
package cn.edu.hactcm.cfcms.utils; import java.io.File; import java.io.FileInputStream; import java. ...
最新文章
- 概率统计笔记:高斯威沙特分布
- arduino电源接口直径多大_求助:Arduino UNO(如下图)有三种供电方式:USB供电,5v(供应芯片,下面一排接口中“...
- Jupyter 绘图怎么显示中文
- EntityFramework Core 5.0 VS SQLBulkCopy
- 配置Log4j(非常具体)
- Luogu 4244 [SHOI2008]仙人掌图
- java调用kettle批量执行
- mysql master 监控_可用于监控 mysql Master Slave 状态的python代码
- 对Python中yield的理解
- 最好用的十六进制编辑器010 Editor
- HJ6302网关模块与富士PXR5系列温控器的通讯
- 网吧服务器组装方案,网吧服务器配置方案有哪些
- curl 命令的使用
- 动态规划之《高楼扔鸡蛋》问题详解 LeetCode 887.鸡蛋掉落
- python批量分析表格_老板让我从几百个Excel中查找数据,我用Python一分钟搞定!...
- AD中画圆弧形板框的方法
- 基于单片机的音乐播放器设计
- 论文阅读(11) 操纵涡环来提高机动性 (2015)
- 美国研究生统计学专业申请及就业情况浅析
- 计算机设备维护保养和网络巡检,弱电设备的维护保养及巡检管理制度
热门文章
- B站 唐宇迪 深度学习笔记
- 干货 | 台大“一天搞懂深度学习”课程PPT(下载方式见文末!!)
- 【评测】荧光标签cas9核酸酶
- 数据服务2- 物理层二
- OpenCV学习笔记~VS code1.25.0.0环境中配置opencv
- GJB 9001C质量管理体系文件构建(2、质量手册编制要点)第1章--第5章
- 磁盘切换成F2FS文件系统并加密
- UnicodeDecodeError: 'utf-8' codec can't decode byte 0x9c in position 1: invalid start byte
- vos3000软交换平台与网关之间的连接
- 移动软交换技术在3G核心网中的实现