【发布时间】:2024-04-22 16:15:01
【问题描述】:
编辑:这似乎不可能,请参阅https://bugs.openjdk.java.net/browse/JDK-8039910。
我有一个提供Stream<Path> 的助手类。这段代码只是包装了Files.walk 并对输出进行排序:
public Stream<Path> getPaths(Path path) {
return Files.walk(path, FOLLOW_LINKS).sorted();
}
由于遵循符号链接,如果文件系统中出现循环(例如符号链接 x -> .),Files.walk 中使用的代码会抛出 UncheckedIOException 包装 FileSystemLoopException 的实例。
在我的代码中,我想捕获此类异常,例如,只记录一条有用的消息。一旦发生这种情况,生成的流可能/应该停止提供条目。
我尝试将.map(this::catchException) 和.peek(this::catchException) 添加到我的代码中,但在此阶段没有捕获到异常。
Path checkException(Path path) {
try {
logger.info("path.toString() {}", path.toString());
return path;
} catch (UncheckedIOException exception) {
logger.error("YEAH");
return null;
}
}
如果有的话,我怎样才能在我的代码中捕获一个UncheckedIOException,发出一个Stream<Path>,这样路径的使用者就不会遇到这个异常?
例如,下面的代码应该永远不会遇到异常:
List<Path> paths = getPaths().collect(toList());
现在,异常是由调用 collect 的代码触发的(我可以在那里捕获异常):
java.io.UncheckedIOException: java.nio.file.FileSystemLoopException: /tmp/junit5844257414812733938/selfloop
at java.nio.file.FileTreeIterator.fetchNextIfNeeded(FileTreeIterator.java:88)
at java.nio.file.FileTreeIterator.hasNext(FileTreeIterator.java:104)
at java.util.Iterator.forEachRemaining(Iterator.java:115)
at java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
at ...
编辑:我提供了一个简单的 JUnit 测试类。在这个问题中,我要求您通过修改 provideStream 中的代码来修复测试。
package somewhere;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static java.nio.file.FileVisitOption.FOLLOW_LINKS;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.nullValue;
import static org.hamcrest.core.IsNot.not;
import static org.junit.Assert.fail;
public class StreamTest {
@Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();
@Test
public void test() throws Exception {
Path rootPath = Paths.get(temporaryFolder.getRoot().getPath());
createSelfloop();
Stream<Path> stream = provideStream(rootPath);
assertThat(stream.collect(Collectors.toList()), is(not(nullValue())));
}
private Stream<Path> provideStream(Path rootPath) throws IOException {
return Files.walk(rootPath, FOLLOW_LINKS).sorted();
}
private void createSelfloop() throws IOException {
String root = temporaryFolder.getRoot().getPath();
try {
Path symlink = Paths.get(root, "selfloop");
Path target = Paths.get(root);
Files.createSymbolicLink(symlink, target);
} catch (UnsupportedOperationException x) {
// Some file systems do not support symbolic links
fail();
}
}
}
【问题讨论】:
-
看起来像 *.com/q/22867286/4856258 的副本。简而言之:您无法使用
Files.walk解决此问题,您必须为此编写完全独立的方法或使用第三方库。 -
我把那个方法放在 completablefuture.suppltasync 上,然后添加异常来捕获那个异常?
-
我不明白你在说什么,@gaston。
-
Future
f=CompletableFuture.supplyAsync (/*产生任务的可调用类*/).exceptionally ((Throwable t )-> {/*检查异常并返回null或默认值*/ }; f.get()//获取测试结果 -
我觉得一个正确的答案可能比这样的 cmets 更有帮助 - 我还是不明白你,对不起。
标签: java exception exception-handling java-stream