全局理解
Glob understanding
我需要在 java 中使用以下选项/参数开发一个文件扫描器:
- 一个目录
- 一个或多个模式,例如 *.xml、*.txt、*test.csv
- 切换为递归扫描
我认为最好的方法是这样的:
public class FileScanningTest {
public static void main(String[] args) throws IOException {
String directory = "C:\tmp\scanning\";
String glob = "**/*.xml";
Boolean rekursiv = false;
final PathMatcher pathMatcher = FileSystems.getDefault().getPathMatcher("glob:"+glob);
Files.walkFileTree(Paths.get(directory), new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) throws IOException {
if (pathMatcher.matches(path)) {
System.out.println(path);
}
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
return FileVisitResult.CONTINUE;
}
});
}
}
我不明白为什么我要在我的实际模式前面加上“**/”。这也确实使扫描递归。如果我删除 **/,应用程序将不会再找到任何东西。
https://docs.oracle.com/javase/tutorial/essential/io/fileOps.html#glob 表示 ** 表示递归,但如果我删除它,为什么它不起作用?
有人可以给我提示吗?
谢谢大家,周末愉快
*
和 **
的区别在于 *
永远不会匹配目录分隔符(/
或 \
取决于您的 OS), 但 **
会。给定这样的文件树:
a/
b.xml
c/
a.xml
da.xml
模式 *a.xml
将仅匹配 da.xml
(不匹配 c/a.xml
,因为它包含 /
),而模式 **a.xml
将同时匹配 da.xml
和 c/a.xml
,模式 a**.xml
将只匹配 a/b.xml
.
要使用从目录 /tmp/scanning/
开始的 glob 递归查找 *.xml
,请查看此示例。它与 Linux Ubuntu 一起工作,可以做你想做的事。它的工作方式类似于 Unix 查找实用程序。除了 Ubuntu,我没有在其他 OS 上测试它,但您应该只需要更改文件名分隔符。
import java.io.*;
import java.nio.file.*;
import java.nio.file.attribute.*;
import static java.nio.file.FileVisitResult.*;
import static java.nio.file.FileVisitOption.*;
import java.util.*;
public class FileScanningTest {
public static class Finder
extends SimpleFileVisitor<Path> {
private final PathMatcher matcher;
private int numMatches = 0;
Finder(String pattern) {
matcher = FileSystems.getDefault()
.getPathMatcher("glob:" + pattern);
}
// Compares the glob pattern against
// the file or directory name.
void find(Path file) {
Path name = file.getFileName();
if (name != null && matcher.matches(name)) {
numMatches++;
System.out.println(file);
}
}
// Prints the total number of
// matches to standard out.
void done() {
System.out.println("Matched: "
+ numMatches);
}
// Invoke the pattern matching
// method on each file.
@Override
public FileVisitResult visitFile(Path file,
BasicFileAttributes attrs) {
find(file);
return CONTINUE;
}
// Invoke the pattern matching
// method on each directory.
@Override
public FileVisitResult preVisitDirectory(Path dir,
BasicFileAttributes attrs) {
find(dir);
return CONTINUE;
}
@Override
public FileVisitResult visitFileFailed(Path file,
IOException exc) {
System.err.println(exc);
return CONTINUE;
}
}
public static void main(String[] args)
throws IOException {
boolean recursive = false;
Path startingDir = Paths.get("/tmp/scanning");
String pattern = "*.{html,xml}";
Finder finder = new Finder(pattern);
if (!recursive) {
Path dir = startingDir;
List<File> files = new ArrayList<>();
try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir, "*.{xml,html}")) {
for (Path entry : stream) {
files.add(entry.toFile());
}
for (File xmlfile : files) {
System.out.println(xmlfile);
}
} catch (IOException x) {
throw new RuntimeException(String.format("error reading folder %s: %s",
dir,
x.getMessage()),
x);
}
} else {
Files.walkFileTree(startingDir, finder);
finder.done();
}
}
}
测试
~> java FileScanningTest
/tmp/scanning/dir2/test2.xml
/tmp/scanning/blah.xml
Matched: 2
如果要匹配 *.xml
或 test3.html
,则可以使用此模式:String pattern = "{*.xml,test3.html}";
我需要在 java 中使用以下选项/参数开发一个文件扫描器:
- 一个目录
- 一个或多个模式,例如 *.xml、*.txt、*test.csv
- 切换为递归扫描
我认为最好的方法是这样的:
public class FileScanningTest {
public static void main(String[] args) throws IOException {
String directory = "C:\tmp\scanning\";
String glob = "**/*.xml";
Boolean rekursiv = false;
final PathMatcher pathMatcher = FileSystems.getDefault().getPathMatcher("glob:"+glob);
Files.walkFileTree(Paths.get(directory), new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) throws IOException {
if (pathMatcher.matches(path)) {
System.out.println(path);
}
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
return FileVisitResult.CONTINUE;
}
});
}
}
我不明白为什么我要在我的实际模式前面加上“**/”。这也确实使扫描递归。如果我删除 **/,应用程序将不会再找到任何东西。
https://docs.oracle.com/javase/tutorial/essential/io/fileOps.html#glob 表示 ** 表示递归,但如果我删除它,为什么它不起作用?
有人可以给我提示吗?
谢谢大家,周末愉快
*
和 **
的区别在于 *
永远不会匹配目录分隔符(/
或 \
取决于您的 OS), 但 **
会。给定这样的文件树:
a/
b.xml
c/
a.xml
da.xml
模式 *a.xml
将仅匹配 da.xml
(不匹配 c/a.xml
,因为它包含 /
),而模式 **a.xml
将同时匹配 da.xml
和 c/a.xml
,模式 a**.xml
将只匹配 a/b.xml
.
要使用从目录 /tmp/scanning/
开始的 glob 递归查找 *.xml
,请查看此示例。它与 Linux Ubuntu 一起工作,可以做你想做的事。它的工作方式类似于 Unix 查找实用程序。除了 Ubuntu,我没有在其他 OS 上测试它,但您应该只需要更改文件名分隔符。
import java.io.*;
import java.nio.file.*;
import java.nio.file.attribute.*;
import static java.nio.file.FileVisitResult.*;
import static java.nio.file.FileVisitOption.*;
import java.util.*;
public class FileScanningTest {
public static class Finder
extends SimpleFileVisitor<Path> {
private final PathMatcher matcher;
private int numMatches = 0;
Finder(String pattern) {
matcher = FileSystems.getDefault()
.getPathMatcher("glob:" + pattern);
}
// Compares the glob pattern against
// the file or directory name.
void find(Path file) {
Path name = file.getFileName();
if (name != null && matcher.matches(name)) {
numMatches++;
System.out.println(file);
}
}
// Prints the total number of
// matches to standard out.
void done() {
System.out.println("Matched: "
+ numMatches);
}
// Invoke the pattern matching
// method on each file.
@Override
public FileVisitResult visitFile(Path file,
BasicFileAttributes attrs) {
find(file);
return CONTINUE;
}
// Invoke the pattern matching
// method on each directory.
@Override
public FileVisitResult preVisitDirectory(Path dir,
BasicFileAttributes attrs) {
find(dir);
return CONTINUE;
}
@Override
public FileVisitResult visitFileFailed(Path file,
IOException exc) {
System.err.println(exc);
return CONTINUE;
}
}
public static void main(String[] args)
throws IOException {
boolean recursive = false;
Path startingDir = Paths.get("/tmp/scanning");
String pattern = "*.{html,xml}";
Finder finder = new Finder(pattern);
if (!recursive) {
Path dir = startingDir;
List<File> files = new ArrayList<>();
try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir, "*.{xml,html}")) {
for (Path entry : stream) {
files.add(entry.toFile());
}
for (File xmlfile : files) {
System.out.println(xmlfile);
}
} catch (IOException x) {
throw new RuntimeException(String.format("error reading folder %s: %s",
dir,
x.getMessage()),
x);
}
} else {
Files.walkFileTree(startingDir, finder);
finder.done();
}
}
}
测试
~> java FileScanningTest
/tmp/scanning/dir2/test2.xml
/tmp/scanning/blah.xml
Matched: 2
如果要匹配 *.xml
或 test3.html
,则可以使用此模式:String pattern = "{*.xml,test3.html}";