tra-loi-cau-hoi-phat-trien-web.com

Làm cách nào để tìm các tệp khớp với chuỗi ký tự đại diện trong Java?

Điều này nên thực sự đơn giản. Nếu tôi có một Chuỗi như thế này:

_../Test?/sample*.txt
_

vậy thì cách nào được chấp nhận chung để có được danh sách các tệp khớp với mẫu này? (ví dụ: nó phải khớp với _../Test1/sample22b.txt_ và _../Test4/sample-spiffy.txt_ nhưng không phải là _../Test3/sample2.blah_ hoặc _../Test44/sample2.txt_)

Tôi đã xem org.Apache.commons.io.filefilter.WildcardFileFilter và có vẻ như đúng là con thú nhưng tôi không chắc làm thế nào để sử dụng nó để tìm tệp trong đường dẫn thư mục tương đối.

Tôi cho rằng tôi có thể tìm nguồn cho kiến ​​vì nó sử dụng cú pháp ký tự đại diện, nhưng tôi phải thiếu một cái gì đó khá rõ ràng ở đây.

( chỉnh sửa : ví dụ trên chỉ là một trường hợp mẫu. Tôi đang tìm cách phân tích các đường dẫn chung có chứa ký tự đại diện khi chạy. Tôi đã tìm ra cách để làm điều đó dựa trên đề xuất của mmyer nhưng thật khó chịu. Chưa kể rằng Java JRE dường như tự động phân tích các ký tự đơn giản trong các đối số chính (Chuỗi []) từ một đối số duy nhất để "lưu "Tôi có thời gian và rắc rối ... Tôi rất vui vì tôi không có các đối số không phải là tệp trong hỗn hợp.)

136
Jason S

Hãy xem xét DirectoryScanner từ Apache Ant:

DirectoryScanner scanner = new DirectoryScanner();
scanner.setIncludes(new String[]{"**/*.Java"});
scanner.setBasedir("C:/Temp");
scanner.setCaseSensitive(false);
scanner.scan();
String[] files = scanner.getIncludedFiles();

Bạn sẽ cần tham khảo ant.jar (~ 1,3 MB cho ant 1.7.1).

71
Misha

Hãy thử FileUtils từ Apache commons-io (phương thức listFilesiterateFiles):

File dir = new File(".");
FileFilter fileFilter = new WildcardFileFilter("sample*.Java");
File[] files = dir.listFiles(fileFilter);
for (int i = 0; i < files.length; i++) {
   System.out.println(files[i]);
}

Để giải quyết vấn đề của bạn với các thư mục TestX, trước tiên tôi sẽ lặp qua danh sách các thư mục:

File[] dirs = new File(".").listFiles(new WildcardFileFilter("Test*.Java");
for (int i=0; i<dirs.length; i++) {
   File dir = dirs[i];
   if (dir.isDirectory()) {
       File[] files = dir.listFiles(new WildcardFileFilter("sample*.Java"));
   }
}

Khá là một giải pháp 'vũ phu' nhưng sẽ hoạt động tốt. Nếu điều này không phù hợp với nhu cầu của bạn, bạn luôn có thể sử dụng RegexFileFilter .

114
Vladimir

Dưới đây là ví dụ về liệt kê các tệp theo mẫu được cung cấp bởi Java 7 nioglobalbing và Java 8 lambdas:

    try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(
            Paths.get(".."), "Test?/sample*.txt")) {
        dirStream.forEach(path -> System.out.println(path));
    }

hoặc là

    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));
    }
47
Vadzim

Bạn có thể chuyển đổi chuỗi ký tự đại diện của mình thành biểu thức chính quy và sử dụng chuỗi đó với phương thức matches của String. Theo ví dụ của bạn:

String original = "../Test?/sample*.txt";
String regex = original.replace("?", ".?").replace("*", ".*?");

Điều này làm việc cho các ví dụ của bạn:

Assert.assertTrue("../Test1/sample22b.txt".matches(regex));
Assert.assertTrue("../Test4/sample-spiffy.txt".matches(regex));

Và ví dụ ngược lại:

Assert.assertTrue(!"../Test3/sample2.blah".matches(regex));
Assert.assertTrue(!"../Test44/sample2.txt".matches(regex));
27
Fabian Steeg

Có thể không giúp bạn ngay bây giờ, nhưng JDK 7 được dự định có khớp tên tệp toàn cầu và regex như một phần của "Các tính năng NIO khác".

18
Tom Hawtin - tackline

Vì Java 8, bạn có thể sử dụng phương thức Files#find trực tiếp từ Java.nio.file.

public static Stream<Path> find(Path start,
                                int maxDepth,
                                BiPredicate<Path, BasicFileAttributes> matcher,
                                FileVisitOption... options)

Ví dụ sử dụng

Files.find(startingPath,
           Integer.MAX_VALUE,
           (path, basicFileAttributes) -> path.toFile().getName().matches(".*.pom")
);
18
Grzegorz Gajos

Thư viện ký tự đại diện có hiệu quả khớp cả tên tệp toàn cầu và regex:

http://code.google.com.vn/p/wildcard/

Việc thực hiện ngắn gọn - JAR chỉ có 12,9 kilobyte.

12
NateS

Cách đơn giản mà không sử dụng bất kỳ nhập khẩu bên ngoài là sử dụng phương pháp này

Tôi đã tạo các tệp csv có tên là billing_201208.csv, billing_201209.csv, billing_201210.csv và có vẻ như nó hoạt động tốt.

Đầu ra sẽ như sau nếu các tệp được liệt kê ở trên tồn tại

found billing_201208.csv
found billing_201209.csv
found billing_201210.csv
[.__.] // Sử dụng Nhập -> nhập Java.io.File [.__.] Chuỗi đích_file; // fileThatYouWantToFilter [.__.] Tệp thư mụcToScan = new File (pathToScan); [.__.] [.__.]
    File[] listOfFiles = folderToScan.listFiles();

     for (int i = 0; i < listOfFiles.length; i++) {
            if (listOfFiles[i].isFile()) {
                target_file = listOfFiles[i].getName();
                if (target_file.startsWith("billing")
                     && target_file.endsWith(".csv")) {
                //You can add these files to fileList by using "list.add" here
                     System.out.println("found" + " " + target_file); 
                }
           }
     }    
}

10
Umair Aziz

Như được đăng trong một câu trả lời khác, thư viện ký tự đại diện hoạt động cho cả khớp tên tệp toàn cầu và regex: http://code.google.com.vn/p/wildcard/

Tôi đã sử dụng mã sau đây để khớp với các mẫu toàn cầu bao gồm tuyệt đối và tương đối trên các hệ thống tệp kiểu * nix:

String filePattern = String baseDir = "./";
// If absolute path. TODO handle windows absolute path?
if (filePattern.charAt(0) == File.separatorChar) {
    baseDir = File.separator;
    filePattern = filePattern.substring(1);
}
Paths paths = new Paths(baseDir, filePattern);
List files = paths.getFiles();

Tôi đã dành một chút thời gian để cố gắng có được các phương thức FileUtils.listFiles trong thư viện Apache commons io (xem câu trả lời của Vladimir) để làm điều này nhưng không thành công (tôi nhận ra bây giờ/nghĩ rằng nó chỉ có thể xử lý mô hình khớp với một thư mục hoặc tệp tại một thời điểm) .

Ngoài ra, sử dụng các bộ lọc regex (xem câu trả lời của Fabian) để xử lý các mẫu toàn cầu loại tuyệt đối do người dùng cung cấp mà không cần tìm kiếm toàn bộ hệ thống tệp sẽ yêu cầu một số tiền xử lý của quả cầu được cung cấp để xác định tiền tố không phải regex/global lớn nhất.

Tất nhiên, Java 7 có thể xử lý tốt chức năng được yêu cầu, nhưng tiếc là hiện tại tôi đang bị mắc kẹt với Java 6. Thư viện tương đối rất nhỏ với kích thước 13,5kb.

Lưu ý cho người đánh giá: Tôi đã cố gắng thêm câu trả lời ở trên vào câu trả lời hiện có đề cập đến thư viện này nhưng bản chỉnh sửa đã bị từ chối. Tôi cũng không có đủ đại diện để thêm nhận xét này. Không có cách nào tốt hơn ...

6
Oliver Coleman

Glob của Java7: Tìm tệp . ( Mẫ )

5

Bạn sẽ có thể sử dụng WildcardFileFilter. Chỉ cần sử dụng System.getProperty("user.dir") để có được thư mục làm việc. Thử đi:

public static void main(String[] args) {
File[] files = (new File(System.getProperty("user.dir"))).listFiles(new WildcardFileFilter(args));
//...
}

Bạn không cần thay thế * bằng [.*], giả sử bộ lọc ký tự đại diện sử dụng Java.regex.Pattern. Tôi chưa thử nghiệm điều này, nhưng tôi thường xuyên sử dụng các mẫu và bộ lọc tệp.

5
Anonymous

Bộ lọc Apache được xây dựng để lặp các tệp trong một thư mục đã biết. Để cho phép ký tự đại diện trong thư mục, bạn sẽ phải chia đường dẫn trên '\' hoặc '/' và thực hiện một bộ lọc trên từng phần riêng biệt.

3
Michael Myers

Tại sao không sử dụng làm một cái gì đó như:

File myRelativeDir = new File("../../foo");
String fullPath = myRelativeDir.getCanonicalPath();
Sting wildCard = fullPath + File.separator + "*.txt";

// now you have a fully qualified path

Sau đó, bạn sẽ không phải lo lắng về các đường dẫn tương đối và có thể thực hiện ký tự đại diện khi cần thiết.

0
Elijah

Phương pháp sử dụng:

public static boolean isFileMatchTargetFilePattern(final File f, final String targetPattern) {
        String regex = targetPattern.replace(".", "\\.");  //escape the dot first
        regex = regex.replace("?", ".?").replace("*", ".*");
        return f.getName().matches(regex);

    }

kiểm tra jUnit:

@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));
        }
    }
}

Đầu ra:

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
0
Tony
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);
0
Anatoliy Shuba

Thực hiện giao diện JDK FileVisitor. Dưới đây là một ví dụ http://wildderator.com/list-files-matching-a-naming-potype-Java/

0
Drona