Java如何获取包含指定内容的SQL文件名称
SQL文件关键词检索实现方案
原代码存在的核心问题
- 路径拼接逻辑错误:原代码只存储了文件的纯名称,读取时直接用文件名生成Path,没有关联目标文件夹的父路径,会导致程序在运行目录下找文件,根本无法读到目标路径下的SQL文件。
- 关键词匹配兼容性差:直接用
l.contains("join")做精确匹配,会漏匹配SQL中最常用的大写写法JOIN,也无法适配大小写混合的书写场景。 - 异常处理失效:空的catch块会吞掉所有文件读取的异常,出现读文件失败的情况时没有任何提示,完全无法排查问题。
- 冗余逻辑:先全量遍历存一遍文件名、再二次循环读文件,做了两次重复的目录遍历操作,效率更低。
优化后的可落地实现逻辑
- 遍历指定目标目录时直接筛选后缀为
.sql的文件,同时保留文件的完整路径信息,省去后续拼接路径的步骤。 - 逐行读取SQL文件内容,匹配关键词时统一转换为小写做比对,覆盖SQL常见的大小写书写场景。
- 只要文件中任意一行命中关键词,就立刻终止该文件的读取,减少不必要的磁盘IO开销,最终把命中的文件名统一收集到结果列表。
- 补充目录合法性校验、读文件错误日志打印,避免异常被静默吞掉。
- 把检索关键词设计为可传入的参数,后续需要检索其他SQL关键词时无需修改核心遍历逻辑。
优化后的可直接运行代码
import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.List; import java.util.Locale; import java.util.stream.Stream; public class SqlKeywordFilter { public static List<String> getMatchedFiles(String targetDirPath, String searchKeyword) throws IOException { List<String> matchedFileNames = new ArrayList<>(); File targetDir = new File(targetDirPath); // 校验目录有效性 if (!targetDir.isDirectory()) { throw new IllegalArgumentException("输入路径不是合法文件夹:" + targetDirPath); } // 筛选目录下所有.sql后缀的文件 File[] sqlFiles = targetDir.listFiles((dir, fileName) -> fileName.toLowerCase(Locale.ROOT).endsWith(".sql") ); if (sqlFiles == null) { return matchedFileNames; } // 逐文件匹配关键词 for (File sqlFile : sqlFiles) { Path filePath = sqlFile.toPath(); boolean isHit = false; try (Stream<String> lineStream = Files.lines(filePath)) { // 忽略大小写匹配关键词,命中即终止读取 isHit = lineStream.anyMatch(line -> line.toLowerCase(Locale.ROOT).contains(searchKeyword.toLowerCase(Locale.ROOT)) ); } catch (IOException e) { System.err.printf("文件[%s]读取失败:%s%n", sqlFile.getName(), e.getMessage()); continue; } if (isHit) { matchedFileNames.add(sqlFile.getName()); } } return matchedFileNames; } public static void main(String[] args) throws IOException { String sqlScriptsDir = "/home/niteshb/wave1-master/wave1/sql/scripts"; String searchKey = "join"; List<String> result = getMatchedFiles(sqlScriptsDir, searchKey); System.out.printf("包含[%s]关键词的SQL文件列表:%n", searchKey); result.forEach(System.out::println); } }
额外适配提示
如果需要更精准的匹配(比如避免把包含"join"字段名的内容误判),可以把原来的字符串包含匹配替换为正则的单词边界匹配,把匹配语句改为:line.toLowerCase(Locale.ROOT).matches(".*\\b" + searchKeyword.toLowerCase(Locale.ROOT) + "\\b.*")
这种写法只会匹配独立的关键词,不会把joint_id、rejoin这类带连续字符的内容误判为命中。
内容的提问来源于stack exchange,提问作者user13593864
相关产品推荐
相关产品推荐

