如何在Java中查找与通配符字符串匹配的文件?
这应该很简单。如果我有这样一个字符串:如何在Java中查找与通配符字符串匹配的文件?,java,file,wildcard,Java,File,Wildcard,这应该很简单。如果我有这样一个字符串: ../Test?/sample*.txt 那么,获得与此模式匹配的文件列表的普遍接受的方法是什么?(例如,它应该匹配。/Test1/sample22b.txt和。/Test4/sample spiffy.txt但不匹配。/Test3/sample2.blah或。/Test44/sample2.txt) 我看了一下,它似乎是正确的beast,但我不确定如何使用它在相对目录路径中查找文件 我想我可以查找ant的源代码,因为它使用通配符语法,但我肯定缺少一些非
../Test?/sample*.txt
那么,获得与此模式匹配的文件列表的普遍接受的方法是什么?(例如,它应该匹配。/Test1/sample22b.txt
和。/Test4/sample spiffy.txt
但不匹配。/Test3/sample2.blah
或。/Test44/sample2.txt
)
我看了一下,它似乎是正确的beast,但我不确定如何使用它在相对目录路径中查找文件
我想我可以查找ant的源代码,因为它使用通配符语法,但我肯定缺少一些非常明显的东西
(edit:上面的示例只是一个示例。我正在寻找在运行时解析包含通配符的常规路径的方法。我根据mmyers的建议找到了如何解析通配符,但这有点烦人。更不用说java JRE似乎在主(String[]参数)中自动解析简单的通配符了从一个参数到“节省”我的时间和麻烦…我很高兴在混合中没有非文件参数。)Apache筛选器是为迭代已知目录中的文件而构建的。若要在目录中也允许使用通配符,您必须在“
\
”或“/
”上拆分路径,并分别对每个部分进行筛选。为什么不使用以下方法:
File myRelativeDir = new File("../../foo");
String fullPath = myRelativeDir.getCanonicalPath();
Sting wildCard = fullPath + File.separator + "*.txt";
// now you have a fully qualified path
这样您就不必担心相对路径,可以根据需要进行通配符编码。现在可能对您没有帮助,但JDK 7打算将glob和regex文件名匹配作为“更多NIO功能”的一部分。您可以将通配符字符串转换为正则表达式,并将其与字符串的
匹配方法一起使用。以你为例:
String original = "../Test?/sample*.txt";
String regex = original.replace("?", ".?").replace("*", ".*?");
这适用于您的示例:
Assert.assertTrue("../Test1/sample22b.txt".matches(regex));
Assert.assertTrue("../Test4/sample-spiffy.txt".matches(regex));
和反例:
Assert.assertTrue("../Test1/sample22b.txt".matches(regex));
Assert.assertTrue("../Test4/sample-spiffy.txt".matches(regex));
Assert.assertTrue(!"../Test3/sample2.blah".matches(regex));
Assert.assertTrue(!"../Test44/sample2.txt".matches(regex));
从(listFiles
和iterateFiles
方法)尝试:
这是一个相当“暴力”的解决方案,但应该可以很好地工作。如果这不符合您的需要,您可以始终使用。考虑Apache Ant的DirectoryScanner:
DirectoryScanner scanner = new DirectoryScanner();
scanner.setIncludes(new String[]{"**/*.java"});
scanner.setBasedir("C:/Temp");
scanner.setCaseSensitive(false);
scanner.scan();
String[] files = scanner.getIncludedFiles();
您需要引用ant.jar(对于ant 1.7.1,大约1.3 MB)。通配符库有效地进行glob和regex文件名匹配:
实现非常简洁——JAR只有12.9千字节。您应该能够使用通配符文件过滤器。只需使用System.getProperty(“user.dir”)
获取工作目录。试试这个:
public static void main(String[] args) {
File[] files = (new File(System.getProperty("user.dir"))).listFiles(new WildcardFileFilter(args));
//...
}
假设通配符筛选器使用java.regex.Pattern
,则不需要将*
替换为[.*]
。我没有对此进行测试,但我经常使用模式和文件过滤器。不使用任何外部导入的简单方法就是使用此方法
我创建了名为billing_201208.csv、billing_201209.csv、billing_201210.csv的csv文件,看起来工作正常
如果存在上面列出的文件,则输出如下
found billing_201208.csv
found billing_201209.csv
found billing_201210.csv
//使用导入->导入java.io.File
公共静态void main(字符串[]args){
字符串pathToScan=“.”;
String target_file;//您想要筛选的文件
File folderToScan=新文件(pathToScan)
File[]listOfFiles=folderToScan.listFiles();
for(int i=0;i
正如另一个答案中所述,通配符库适用于glob和regex文件名匹配:
我使用以下代码来匹配glob模式,包括绝对和相对on*nix样式的文件系统:
try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(
Paths.get(".."), "Test?/sample*.txt")) {
dirStream.forEach(path -> System.out.println(path));
}
我花了一些时间尝试在Apache commons io库中获取FileUtils.listFiles方法(参见Vladimir的回答),但没有成功(我现在意识到/认为它一次只能处理与一个目录或文件匹配的模式)
此外,使用正则表达式过滤器(参见Fabian的答案)处理任意用户提供的绝对类型glob模式而不搜索整个文件系统,需要对提供的glob进行一些预处理,以确定最大的非正则表达式/glob前缀
当然,Java7可以很好地处理请求的功能,但不幸的是,我现在只能使用Java6。该库的大小相对较小,为13.5kb
评审员注意:我试图将上述内容添加到提及此库的现有答案中,但编辑被拒绝。我也没有足够的代表将此添加为评论。难道没有更好的方法…的Java7:。()实现JDK FileVisitor接口。以下是一个示例以下是按Java 8和lambdas支持的模式列出文件的示例:
PathMatcher pathMatcher = FileSystems.getDefault()
.getPathMatcher("regex:Test./sample\\w+\\.txt");
try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(
new File("..").toPath(), pathMatcher::matches)) {
dirStream.forEach(path -> System.out.println(path));
}
try(DirectoryStream dirStream=Files.newDirectoryStream(
path.get(“…”,“Test?/sample*.txt”)){
dirStream.forEach(路径->系统输出.println(路径));
}
或
PathMatcher PathMatcher=FileSystems.getDefault()
.getPathMatcher(“regex:Test./sample\\w+\\.txt”);
try(DirectoryStream dirStream=Files.newDirectoryStream(
新文件(“..”.toPath(),pathMatcher::matches)){
dirStream.forEach(路径->系统输出.println(路径));
}
Util方法:
@Test
public void testIsFileMatchTargetFilePattern() {
String dir = "D:\\repository\\org\my\\modules\\mobile\\mobile-web\\b1605.0.1";
String[] regexPatterns = new String[] {"_*.repositories", "*.pom", "*-b1605.0.1*","*-b1605.0.1", "mobile*"};
File fDir = new File(dir);
File[] files = fDir.listFiles();
for (String regexPattern : regexPatterns) {
System.out.println("match pattern [" + regexPattern + "]:");
for (File file : files) {
System.out.println("\t" + file.getName() + " matches:" + FileUtils.isFileMatchTargetFilePattern(file, regexPattern));
}
}
}
jUnit测试:
match pattern [_*.repositories]:
mobile-web-b1605.0.1.pom matches:false
mobile-web-b1605.0.1.war matches:false
_remote.repositories matches:true
match pattern [*.pom]:
mobile-web-b1605.0.1.pom matches:true
mobile-web-b1605.0.1.war matches:false
_remote.repositories matches:false
match pattern [*-b1605.0.1*]:
mobile-web-b1605.0.1.pom matches:true
mobile-web-b1605.0.1.war matches:true
_remote.repositories matches:false
match pattern [*-b1605.0.1]:
mobile-web-b1605.0.1.pom matches:false
mobile-web-b1605.0.1.war matches:false
_remote.repositories matches:false
match pattern [mobile*]:
mobile-web-b1605.0.1.pom matches:true
mobile-web-b1605.0.1.war matches:true
_remote.repositories matches:false
输出:
public static Stream<Path> find(Path start,
int maxDepth,
BiPredicate<Path, BasicFileAttributes> matcher,
FileVisitOption... options)
由于Java8,您可以直接从Java.nio.file
使用Files#find
方法
Files.find(startingPath,
Integer.MAX_VALUE,
(path, basicFileAttributes) -> path.toFile().getName().matches(".*.pom")
);
仅使用Java流
String startingdir="The directory name";
String filenameprefix="The file pattern"
File startingDirFile=new File(startingdir);
final File[] listFiles=startingDirFile.listFiles(new FilenameFilter() {
public boolean accept(File arg0,String arg1)
{System.out.println(arg0+arg1);
return arg1.matches(filenameprefix);}
});
System.out.println(Arrays.toString(listFiles));
Path testPath=Path.get(“C:\”;
溪流=
查找(testPath,1,
(路径,基本文件属性)->{
File File=path.toFile();
返回文件.get
match pattern [_*.repositories]:
mobile-web-b1605.0.1.pom matches:false
mobile-web-b1605.0.1.war matches:false
_remote.repositories matches:true
match pattern [*.pom]:
mobile-web-b1605.0.1.pom matches:true
mobile-web-b1605.0.1.war matches:false
_remote.repositories matches:false
match pattern [*-b1605.0.1*]:
mobile-web-b1605.0.1.pom matches:true
mobile-web-b1605.0.1.war matches:true
_remote.repositories matches:false
match pattern [*-b1605.0.1]:
mobile-web-b1605.0.1.pom matches:false
mobile-web-b1605.0.1.war matches:false
_remote.repositories matches:false
match pattern [mobile*]:
mobile-web-b1605.0.1.pom matches:true
mobile-web-b1605.0.1.war matches:true
_remote.repositories matches:false
public static Stream<Path> find(Path start,
int maxDepth,
BiPredicate<Path, BasicFileAttributes> matcher,
FileVisitOption... options)
Files.find(startingPath,
Integer.MAX_VALUE,
(path, basicFileAttributes) -> path.toFile().getName().matches(".*.pom")
);
Path testPath = Paths.get("C:\");
Stream<Path> stream =
Files.find(testPath, 1,
(path, basicFileAttributes) -> {
File file = path.toFile();
return file.getName().endsWith(".java");
});
// Print all files found
stream.forEach(System.out::println);
String startingdir="The directory name";
String filenameprefix="The file pattern"
File startingDirFile=new File(startingdir);
final File[] listFiles=startingDirFile.listFiles(new FilenameFilter() {
public boolean accept(File arg0,String arg1)
{System.out.println(arg0+arg1);
return arg1.matches(filenameprefix);}
});
System.out.println(Arrays.toString(listFiles));