我是靠谱客的博主 淡然红牛,最近开发中收集的这篇文章主要介绍递归扫描文件设置深度_Android丨手把手教你实现网上文件的快速扫描,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

Android作为一种基于Linux的自由及开放源代码的操作系统,多年来与iOS构成双垄断的局面,占据移动操作系统的半壁江山,拥有非常广泛的客户群。

936c8406b3be649260a640578b68aec7.png

诚迈科技是早期加入Android市场的软件供应商之一,多年来为相关客户提供全套的Android操作系统解决方案,在手机、平板、汽车等行业都做出了不错的成绩,有丰富的技术开发经验。

诚迈科技在本文要和大家分享的是——Android开发之网上文件快速扫描的实操指南。

网上文件快速扫描分为两种:

一、依赖系统的MediaStore,即等待系统扫描完成后,再去读取数据库,这一种依赖性太强,而且部分OS在一块的处理逻辑并不一样,兼容性较差,速度也不太快。

二、在Java中编写文件的目录层次递归扫描,这种耦合性和依赖性较低,但是这种方法却又较慢,毕竟Java的执行速度就比C要慢。

下面,我们介绍一种采用JNI编写的快速文件扫描。阅读本文章需要一定的JNI编程基础,同时也需要对Linux下的C语言的库函数有一定的了解。

这里就不细说如何创建AS工程,直接上干货:

代码设计思路:JAVA层代码通过调用native方法并传入需要扫描的目录路径进入到JNI的so库中的相关方法中,然后在so库中对目录路径下的子文件进行遍历扫描,若包含子目录,则进入递归扫描状态,扫描到文件后,将文件路径回传给java层,java层收到文件路径后,可以先add到一个List中,待完全退出native方法后,对该List进行统一处理。

在cpp目录下,创建scan.cpp,include相关的头文件,核心代码如下:

extern "C"

void readFileList(JNIEnv* env, jobject thiz, const char *basePath)

{

    DIR *dir;

    struct dirent *ptr;

    if ((dir = opendir(basePath)) == NULL) {

        LOGE("Open dir error: %sn", basePath);

        return;

    }

    while ((ptr=readdir(dir)) != NULL) {

        if(strcmp(ptr->d_name,".")==0 || strcmp(ptr->d_name,"..")==0 ||

           (strchr(ptr->d_name, '.') != NULL

           && strcmp(ptr->d_name, strchr(ptr->d_name, '.')) == 0) ) {

            continue;

        } else if(ptr->d_type == 8) { // file

            // basePath + ptr->d_name 就是文件的完整路径,此时可以回传给java层

        } else if(ptr->d_type == 4) {   // dir

            char dirFilePath[1000];

            memset(dirFilePath, '', sizeof(dirFilePath));

            strcpy(dirFilePath, basePath);

            strcat(dirFilePath, "/");

            strcat(dirFilePath, ptr->d_name);

            readFileList(env, thiz, dirFilePath);

        } else if(ptr->d_type == 0) {   //unknown

            char fileWhole[1000];

            memset(fileWhole, '', sizeof(fileWhole));

            strcpy(fileWhole, basePath);

            strcat(fileWhole, "/");

            strcat(fileWhole, ptr->d_name);

            struct stat statbuf;

            if(stat(fileWhole, &statbuf) == -1){  //unknow error

                LOGI("unknowFile:%s/%sn",basePath,ptr->d_name);

                continue;

            }

            if(S_ISREG(statbuf.st_mode)){   // file

                // fileWhole 就是文件的完整路径,此时可以回传给java层

            } else if(S_ISDIR(statbuf.st_mode)){// dir

                readFileList(env, thiz, fileWhole);

            }

        }

    }

    closedir(dir);

}

该代码逻辑简单实用,通过opendir和readdir来打开读取目录,循环来反复读取判断当前的文件节点dirent,根据d_type值来判断是文件还是文件夹:

  • l   首先需要过滤“.”和“..”,这两个前者是本目录的引用,后者是父目录的,当然也需要判断是否是隐藏文件,

  • l   d_type值为8即是文件,可以通过文件后缀来判定是否是需要的文件

  • l   d_type值为4表示文件夹,可以递归调用readFileList来读取文件夹中的内容

  • l   值得注意的是,部分文件或文件夹的d_type值为0,此时可以通过中的stat函数来获得该文件的详细信息,再通过S_ISREG和S_ISDIR宏定义来判定到底是文件还是文件夹。

判定是文件夹后,检测文件后缀是否是自己想要的,若不是就丢弃,否则可以通过JNI中的CallVoidMethod调用到JAVA层的相对应的方法,并把文件路径传递过去。然后在java层对传递过来的数据进行汇总,待JNI把整个目录扫描完退出后,再统一处理。建议大家把文件路径回传给java层,当然自己在CPP中维护一个数组也行,具体看自己的需求。最后需要调用closedir来关闭打开的文件夹。

另外,这套代码也可以只扫描指定路径,这样提高代码复用,降低耦合。

假如这段代码正在扫描TF卡,而TF卡被强行拔出,那么这段代码该怎么终止扫描呢?

实际上这段代码因为关键字extern "C"而会被编译成C,C里面没有异常这一说,强行拔出TF卡后,在调用readdir函数时,会直接返回NULL,这样就退出了循环。JAVA层在收到UNMOUNTED或EJECT广播后需要对这段代码以前执行回传的文件路径做修正校验或清除处理,这个也看各自的需求。

这篇指南是不是很容易get?采用JNI 编写的这段代码比较简单好用,思路清晰明了,另外C语言执行速度也比较快。在 Android 的世界里,JNI 的重要性可以说是无可代替,虽然平常我们用到的很少,但是了解它的实现原理是让你穿梭在上下层之间的保障。

End

关于诚迈(证券代码:300598)

诚迈科技(南京)股份有限公司成立于2006年9月,智能科技专家,致力于为客户提供全生命周期的解决方案。诚迈科技提供基于主流移动操作系统的软件开发和技术支持服务、移动互联网软件开发和运营服务以及智能终端、智能汽车、智慧城市等解决方案,拥有优质、稳定的客户群体,与知名移动芯片厂商、移动终端设备厂商、汽车厂商以及移动互联网厂商建立了长期稳定的合作关系。

官方网站:www.archermind.com

9545a6283329209119b0aed9ba4218de.png

最后

以上就是淡然红牛为你收集整理的递归扫描文件设置深度_Android丨手把手教你实现网上文件的快速扫描的全部内容,希望文章能够帮你解决递归扫描文件设置深度_Android丨手把手教你实现网上文件的快速扫描所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(53)

评论列表共有 0 条评论

立即
投稿
返回
顶部