androlua文件遍历工具函数

--[[
AndroLua 文件遍历工具
作者:您的名字
日期:2024年12月18日
功能:递归遍历目录,支持文件过滤和回调处理
]]

require "import"
import "java.io.File"
import "android.os.Environment"
import "android.app.AlertDialog"
import "android.widget.ProgressDialog"

--[[
遍历目录中的所有文件(递归)
参数说明:
  dirPath: 要遍历的目录路径(字符串)
  options: 可选参数表,包含以下字段:
    - filter: 文件过滤器(函数或字符串模式)
             如果是函数:function(fileName, isDir) return true/false end
             如果是字符串:使用Lua模式匹配,如 "%.rpgmvp$" 匹配.rpgmvp文件
    - recursive: 是否递归遍历子目录,默认true
    - maxDepth: 最大递归深度,默认10
    - onFileFound: 找到文件时的回调函数 function(filePath, fileName, isDir)
    - onProgress: 进度回调 function(current, total, currentFile)
返回值:
  文件列表数组,每个元素是包含文件信息的表
]]
function traverseDirectory(dirPath, options)
    -- 参数默认值
    options = options or {}
    local filter = options.filter
    local recursive = options.recursive == nil and true or options.recursive
    local maxDepth = options.maxDepth or 10
    local onFileFound = options.onFileFound
    local onProgress = options.onProgress
    
    -- 验证目录
    local dir = File(dirPath)
    if not dir.exists() then
        print("错误:目录不存在 - " .. dirPath)
        return {}
    end
    
    if not dir.isDirectory() then
        print("错误:路径不是目录 - " .. dirPath)
        return {}
    end
    
    -- 结果列表
    local results = {}
    
    -- 内部递归函数
    local function search(currentPath, currentDepth, relativePath)
        if currentDepth > maxDepth then
            return 0
        end
        
        local currentDir = File(currentPath)
        local files = currentDir.listFiles()
        if not files then
            return 0
        end
        
        local count = 0
        local len = #files
        
        for i = 0, len - 1 do
            local file = files[i]
            local fileName = file.getName()
            local isDir = file.isDirectory()
            local filePath = file.getAbsolutePath()
            
            -- 计算相对路径
            local newRelativePath
            if relativePath == "" then
                newRelativePath = fileName
            else
                newRelativePath = relativePath .. "/" .. fileName
            end
            
            -- 检查是否通过过滤器
            local shouldInclude = true
            
            if filter then
                if type(filter) == "function" then
                    shouldInclude = filter(fileName, isDir)
                elseif type(filter) == "string" then
                    -- 如果是目录且需要递归,不进行模式过滤
                    if not isDir then
                        shouldInclude = fileName:match(filter) ~= nil
                    end
                end
            end
            
            -- 处理文件
            if shouldInclude then
                local fileInfo = {
                    name = fileName,
                    path = filePath,
                    relativePath = newRelativePath,
                    isDir = isDir,
                    size = file.length(),
                    lastModified = file.lastModified(),
                    depth = currentDepth,
                    parent = currentPath
                }
                
                table.insert(results, fileInfo)
                
                -- 调用回调函数
                if onFileFound then
                    onFileFound(filePath, fileName, isDir, fileInfo)
                end
                
                count = count + 1
            end
            
            -- 递归遍历子目录
            if recursive and isDir then
                count = count + search(filePath, currentDepth + 1, newRelativePath)
            end
            
            -- 进度回调
            if onProgress then
                onProgress(count, #results, filePath)
            end
        end
        
        return count
    end
    
    -- 开始遍历
    print("开始遍历目录: " .. dirPath)
    local total = search(dirPath, 1, "")
    print("遍历完成,找到 " .. #results .. " 个文件/目录")
    
    return results
end

--[[
查找特定类型的文件(便捷函数)
参数:
  dirPath: 目录路径
  extensions: 扩展名数组,如 {"png", "jpg", "jpeg"}
  recursive: 是否递归,默认true
返回值:
  文件列表
]]
function findFilesByExtension(dirPath, extensions, recursive)
    recursive = recursive == nil and true or recursive
    
    -- 构建过滤器函数
    local filter = function(fileName, isDir)
        if isDir then
            return false
        end
        
        for _, ext in ipairs(extensions) do
            if fileName:match("%." .. ext .. "$") then
                return true
            end
        end
        
        return false
    end
    
    return traverseDirectory(dirPath, {
        filter = filter,
        recursive = recursive
    })
end

--[[
获取目录大小(递归计算)
参数:
  dirPath: 目录路径
返回值:
  总大小(字节数)
]]
function getDirectorySize(dirPath)
    local totalSize = 0
    
    traverseDirectory(dirPath, {
        onFileFound = function(filePath, fileName, isDir)
            if not isDir then
                local file = File(filePath)
                totalSize = totalSize + file.length()
            end
        end
    })
    
    return totalSize
end

--[[
显示带进度条的目录遍历(UI版本)
参数:
  activity: AndroLua的activity对象
  dirPath: 目录路径
  onComplete: 完成后的回调函数 function(results)
]]
function traverseDirectoryWithProgress(activity, dirPath, onComplete)
    -- 创建进度对话框
    local progress = ProgressDialog(activity)
    progress.setTitle("正在扫描目录")
    progress.setMessage("请稍候...")
    progress.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL)
    progress.setMax(100)
    progress.setCancelable(false)
    progress.show()
    
    local results = {}
    local totalFiles = 0
    
    -- 在后台线程中遍历
    thread(function()
        results = traverseDirectory(dirPath, {
            onProgress = function(current, total, currentFile)
                -- 更新进度
                activity.runOnUiThread(Runnable{
                    run = function()
                        if total > 0 then
                            local percent = math.floor(current / total * 100)
                            progress.setProgress(percent)
                            progress.setMessage("已扫描 " .. current .. " 个文件\n当前: " .. File(currentFile).getName())
                        end
                    end
                })
            end
        })
        
        -- 完成后关闭进度条
        activity.runOnUiThread(Runnable{
            run = function()
                progress.dismiss()
                if onComplete then
                    onComplete(results)
                end
            end
        })
    end)
end

--[[
示例使用代码
]]
function exampleUsage()
    -- 示例1:遍历目录并打印所有文件
    print("=== 示例1:简单遍历 ===")
    local files = traverseDirectory("/sdcard/Download", {
        onFileFound = function(path, name, isDir)
            local typeStr = isDir and "[目录]" or "[文件]"
            print(typeStr .. " " .. name)
        end
    })
    
    -- 示例2:查找所有图片文件
    print("\n=== 示例2:查找图片文件 ===")
    local images = findFilesByExtension("/sdcard/Pictures", {"png", "jpg", "jpeg"})
    for i, img in ipairs(images) do
        print(i .. ". " .. img.name .. " (" .. math.floor(img.size/1024) .. " KB)")
    end
    
    -- 示例3:获取目录大小
    print("\n=== 示例3:计算目录大小 ===")
    local size = getDirectorySize("/sdcard/Download")
    print("目录大小: " .. formatFileSize(size))
    
    -- 示例4:在UI中使用进度条
    print("\n=== 示例4:带进度条的遍历 ===")
    -- traverseDirectoryWithProgress(activity, "/sdcard/Download", function(results)
    --     print("找到 " .. #results .. " 个文件")
    -- end)
end

--[[
辅助函数:格式化文件大小
]]
function formatFileSize(bytes)
    if bytes < 1024 then
        return bytes .. " B"
    elseif bytes < 1024 * 1024 then
        return string.format("%.2f KB", bytes / 1024)
    elseif bytes < 1024 * 1024 * 1024 then
        return string.format("%.2f MB", bytes / (1024 * 1024))
    else
        return string.format("%.2f GB", bytes / (1024 * 1024 * 1024))
    end
end

--[[
测试函数
]]
function testTraverseFunctions()
    print("=== 文件遍历工具测试 ===")
    
    -- 测试目录是否存在
    local testDir = "/sdcard/DCIM"
    local dir = File(testDir)
    
    if dir.exists() and dir.isDirectory() then
        exampleUsage()
    else
        print("测试目录不存在,使用其他目录...")
        exampleUsage() -- 还是会执行,但可能找到的文件较少
    end
end

-- 如果直接运行此脚本,则执行测试
if not activity then
    print("注意:此脚本需要在AndroLua环境中运行")
else
    -- 在AndroLua中,可以调用 testTraverseFunctions() 进行测试
    print("文件遍历工具加载完成")
    print("可用函数:")
    print("1. traverseDirectory(dirPath, options)")
    print("2. findFilesByExtension(dirPath, extensions)")
    print("3. getDirectorySize(dirPath)")
    print("4. traverseDirectoryWithProgress(activity, dirPath, callback)")
end

-- 导出函数
return {
    traverseDirectory = traverseDirectory,
    findFilesByExtension = findFilesByExtension,
    getDirectorySize = getDirectorySize,
    traverseDirectoryWithProgress = traverseDirectoryWithProgress,
    formatFileSize = formatFileSize,
    test = testTraverseFunctions
}

 

posted on 2025-12-19 08:30  小沙盒工作室  阅读(0)  评论(0)    收藏  举报