--[[
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
}