Dlaczego wyjątek rzucania Java 7 Files.walkFileTree przy napotkaniu pliku tar na dysku zdalnym
UżywamFiles.WalkFileTree()
aby poruszać się po folderze i liczyć pliki audio, ale jest problem, gdy napotka plik tar, wydaje się, że traktuje go jako rzeczywisty folder, którego oczekiwałem po prostu przeskoczyć.
Nie widzę żadnych opcji, które pozwoliłyby mi kontrolować to zachowanie
Kod:
package com.jthink.songkong.fileloader;
import com.jthink.songkong.cmdline.SongKong;
import com.jthink.songkong.ui.MainWindow;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.concurrent.Callable;
import java.util.logging.Level;
/**
* Count the number of files that can be loaded, for information purposes only
*/
public class CountFilesinFolder implements Callable<Boolean> {
public static class CountFiles
extends SimpleFileVisitor<Path> {
private int fileCount = 0;
private final PathMatcher matcher;
CountFiles(String pattern) {
matcher =
FileSystems.getDefault()
.getPathMatcher("regex:" + pattern);
}
/**
* Find Music file
*
* @param file
* @param attr
* @return
*/
@Override
public FileVisitResult visitFile(Path file,
BasicFileAttributes attr) {
Path name = file.getFileName();
if (name != null && matcher.matches(name)) {
fileCount++;
}
return FileVisitResult.CONTINUE;
}
public int getFileCount() {
return fileCount;
}
}
private Path scanDir;
public CountFilesinFolder(Path scanDir) {
this.scanDir = scanDir;
}
public Boolean call() {
CountFiles countFiles = null;
try {
countFiles = new CountFiles("^(?!._).*[.](?:mp3|mp4|m4p|m4b|m4a|ogg|flac|wma)$");
Files.walkFileTree(scanDir, countFiles);
}
catch (Exception e) {
MainWindow.logger.log(Level.SEVERE, "Unable to find file for deriving base folder", e);
}
MainWindow.logger.severe("Music File Count:"+countFiles.getFileCount());
SongKong.setMaxProgress(countFiles.getFileCount());
return true;
}
}
daje ten stacktrace
java.nio.file.NoSuchFileException: Z:\Scratch\fred.tar
at sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:79)
at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:97)
at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:102)
at sun.nio.fs.WindowsDirectoryStream.<init>(WindowsDirectoryStream.java:86)
at sun.nio.fs.WindowsFileSystemProvider.newDirectoryStream(WindowsFileSystemProvider.java:526)
at java.nio.file.Files.newDirectoryStream(Files.java:411)
at java.nio.file.FileTreeWalker.walk(FileTreeWalker.java:179)
at java.nio.file.FileTreeWalker.walk(FileTreeWalker.java:199)
at java.nio.file.FileTreeWalker.walk(FileTreeWalker.java:69)
at java.nio.file.Files.walkFileTree(Files.java:2591)
at java.nio.file.Files.walkFileTree(Files.java:2624)
at com.jthink.songkong.fileloader.CountFilesinFolder.call(CountFilesinFolder.java:68)
at com.jthink.songkong.fileloader.CountFilesinFolder.call(CountFilesinFolder.java:15)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
at java.util.concurrent.FutureTask.run(FutureTask.java:166)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)
ale to jest dysk zdalny (dysk nas), nie dostaję takiego błędu na dysku lokalnym
EDYTOWAĆ Zaimplementowałem następującą odpowiedź na poniższą odpowiedź: pomyślałem, że działa
@Override
public FileVisitResult preVisitDirectory(Path dir,
BasicFileAttributes attrs)
throws IOException {
if(dir.endsWith(".tar"))
{
return FileVisitResult.SKIP_SUBTREE;
}
return super.preVisitDirectory(dir, attrs);
}
ale moje testy były nieudane, w rzeczywistości nie działa, ponieważ kod w FileTreeWalker, który się nie powiedzie, jest wywoływany przed metodą previsit
try {
DirectoryStream<Path> stream = null;
FileVisitResult result;
// open the directory
try {
stream = Files.newDirectoryStream(file);
} catch (IOException x) {
return visitor.visitFileFailed(file, x);
} catch (SecurityException x) {
// ignore, as per spec
return FileVisitResult.CONTINUE;
}
// the exception notified to the postVisitDirectory method
IOException ioe = null;
// invoke preVisitDirectory and then visit each entry
try {
result = visitor.preVisitDirectory(file, attrs);
if (result != FileVisitResult.CONTINUE) {
return result;
}