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文件夹内的文件地址相关推荐

  1. Android 获取assets文件夹中音频文件的引用,并播放音乐

    //本地app中的assets文件夹有music_1.mp3的文件,那么怎么获取文件引用,并直接播放这个文件呢     private void playMusic(boolean play) {   ...

  2. vue获取本地文件夹内所有图片

    <script> const path = require("path"); //读取文件的路径 是否遍历文件的子目录 匹配文件正则表达式 const files = ...

  3. php过去文件夹总数,用php获取文件夹内文件的数量

    欢迎进入Linux社区论坛,与200万技术人员互动交流 >>进入 用php获取指定文件夹内文件的数量: 用PHP读取一个文件夹内有多少个文件,例如有一个Picture文件夹,里面有200张 ...

  4. Python 获取当前文件夹所有文件名并写入到excel文件中

    在工作中,有时候,我们需要整理文件夹中的所有文件名称,并罗列在一张表格中.天哪,我的文件夹中有上千个文件,要一个个的复制粘贴吗?太麻烦了吧?今天,我们用Python来解决这个问题. 1. 使用方法: ...

  5. Android基础篇 访问Assets文件夹里面的资源【文本、图片、音频、字体包】

    一.创建Assest文件夹 直接把资源复制粘贴到该文件夹下 (1)获取Assets文件夹的管理类 AssetManager assets = getAssets(); (2)遍历文件夹下的资源列表 S ...

  6. assets android 作用,Android assets文件夹之位置放置和作用

    Android 的assets文件夹的放置位置,Eclipse创建项目时就生成了的,Android Studio则不太一样,AS可以包含几种方式, 1:可以在build.gradle文件下配置,加如下 ...

  7. SFTP获取文件夹内的文件名,文件大小,文件修改时间

    SFTP获取文件夹内的文件名,文件大小,文件修改时间 使用SFTP协议获取服务上的指定路径的文件夹下的所有文件名,文件大小,文件的修改时时间等. 工具类 import java.io.File; im ...

  8. 使用python将歌词文件(.lrc文件)转换成字典及遍历获取文件夹内所有lrc文件并以lrc格式显示出来

    import os class Get_lrcs(): #将lrc文件转换成字典def lrc_to_dict(file_path:str,filenmae:str): #需要传入的参数:文件路径,文 ...

  9. Java获取文件大小,文件夹内文件个数的工具类

    package cn.edu.hactcm.cfcms.utils; import java.io.File; import java.io.FileInputStream; import java. ...

最新文章

  1. 概率统计笔记:高斯威沙特分布
  2. arduino电源接口直径多大_求助:Arduino UNO(如下图)有三种供电方式:USB供电,5v(供应芯片,下面一排接口中“...
  3. Jupyter 绘图怎么显示中文
  4. EntityFramework Core 5.0 VS SQLBulkCopy
  5. 配置Log4j(非常具体)
  6. Luogu 4244 [SHOI2008]仙人掌图
  7. java调用kettle批量执行
  8. mysql master 监控_可用于监控 mysql Master Slave 状态的python代码
  9. 对Python中yield的理解
  10. 最好用的十六进制编辑器010 Editor
  11. HJ6302网关模块与富士PXR5系列温控器的通讯
  12. 网吧服务器组装方案,网吧服务器配置方案有哪些
  13. curl 命令的使用
  14. 动态规划之《高楼扔鸡蛋》问题详解 LeetCode 887.鸡蛋掉落
  15. python批量分析表格_老板让我从几百个Excel中查找数据,我用Python一分钟搞定!...
  16. AD中画圆弧形板框的方法
  17. 基于单片机的音乐播放器设计
  18. 论文阅读(11) 操纵涡环来提高机动性 (2015)
  19. 美国研究生统计学专业申请及就业情况浅析
  20. 计算机设备维护保养和网络巡检,弱电设备的维护保养及巡检管理制度

热门文章

  1. B站 唐宇迪 深度学习笔记
  2. 干货 | 台大“一天搞懂深度学习”课程PPT(下载方式见文末!!)
  3. 【评测】荧光标签cas9核酸酶
  4. 数据服务2- 物理层二
  5. OpenCV学习笔记~VS code1.25.0.0环境中配置opencv
  6. GJB 9001C质量管理体系文件构建(2、质量手册编制要点)第1章--第5章
  7. 磁盘切换成F2FS文件系统并加密
  8. UnicodeDecodeError: 'utf-8' codec can't decode byte 0x9c in position 1: invalid start byte
  9. vos3000软交换平台与网关之间的连接
  10. 移动软交换技术在3G核心网中的实现