android - 文件的批量元数据请求

标签 android kotlin filesystems

它基本上归结为:如果我在一个目录中有 4000 个文件,则 File.isDirectory() 函数需要 1ms 来执行,因此该目录需要 4s 来计算(太慢 [1])。

我没有最完整的文件系统知识,但我认为 isDirectory() 可以针对目录中的所有元素进行批处理(读取一大块数据,然后分离单个文件的元数据)。 C/C++ 代码是可接受的(它可以与 JNI 一起运行),但应作为最后的资源。

我找到了FileVisitor ,但它似乎不是解决我的问题的最佳方法,因为我不必访问整个文件树。我还找到了BasicFileAttributeView但它似乎有同样的问题。 This是一个相关的问题,但没有提供重要解决方案的答案。

[ 1 ]:因为这不是我唯一做的事情,所以最终像 17 岁。

编辑:代码:

internal fun workFrom(unit: ProcessUnit<D>) {
    launch {
        var somethingAddedToPreload = false
        val file = File(unit.first)

        ....

        //Load children folders
        file.listFiles(FileFilter {
            it.isDirectory
        })?.forEach {
            getPreloadMapMutex().withLock {
                if (getPreloadMap()[it.path] == null) {
                    val subfiles = it.list() ?: arrayOf()
                    for (filename in subfiles) {
                        addToProcess(it.path, ProcessUnit(it.path + DIVIDER + filename, unit.second))
                    }

                    getPreloadMap()[it.path] = PreloadedFolder(subfiles.size)
                    if (getPreloadMap().size > PRELOADED_MAP_MAXIMUM) cleanOldEntries()
                    getDeleteQueue().add(it.path)

                    somethingAddedToPreload = somethingAddedToPreload || subfiles.isNotEmpty()
                }
            }
        }

        ...

        if(somethingAddedToPreload) {
            work()
        }
    }
}

private fun addToProcess(path: String, unit: ProcessUnit<D>) {
    val f: () -> Pair<String, FetcherFunction<D>> = { load(path, unit) }
    preloadList.add(f)
}

private suspend fun work() {
    preloadListMutex.withLock {
        preloadList.forEach {
            launch {
                val (path, data) = it.invoke()

                if (FilePreloader.DEBUG) {
                    Log.d("FilePreloader.Processor", "Loading from $path: $data")
                }

                val list = getPreloadMap()[path]
                        ?: throw IllegalStateException("A list has been deleted before elements were added. We are VERY out of memory!")
                list.add(data)
            }
        }
        preloadList.clear()
    }
}

PS:我会在进行优化之前删除工作中的协程,完整代码是here .

最佳答案

您可以运行 ls -F 并通过查看最后一个字符来检查文件是否为目录的输出,目录将以 / 结尾。例如

val cmd = "ls -F ${myFile.absolutePath}"
val process = Runtime.getRuntime().exec(cmd)
val files = process.inputStream
        .bufferedReader()
        .use(BufferedReader::readText)
        .lines()

for (fileName in files) {
    val isDir = fileName.endsWith("/")
}

我在模拟器上运行了一个快速测试,有 4000 个文件和 4000 个目录,整个过程大约需要 150 毫秒。

关于android - 文件的批量元数据请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49480264/

相关文章:

android - SoundPool 听起来没有变化

android - Kotlin 缺少提供程序的 Dagger 2 错误

kotlin.NotImplementedError : An operation is not implemented: not implemented

macos - 使用应用范围的安全书签从系统位置删除文件

java - 客户端关闭后,Android TCP 服务器仅显示来自 Python 客户端的消息

java - 对话框在主 Activity 中触发非静态方法

android - 谷歌地图 fragment 中的 SupportMapFragment 错误

stream - RxJava - 将 Observable 转换为迭代器、流或序列

winapi - FS在Win32中注册

perl - 使用 Perl 在 unix 上获取目录和子目录大小的最快方法是什么?