gpt4 book ai didi

java - 在 Java 8 流中捕获 UncheckedIOException

转载 作者:塔克拉玛干 更新时间:2023-11-02 19:52:33 26 4
gpt4 key购买 nike

编辑:这似乎不可能,请参阅 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();
}

由于遵循符号链接(symbolic link),如果文件系统中出现循环(例如符号链接(symbolic link) 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();
}
}
}

最佳答案

您可以制作自己的步行流工厂:

public class FileTree {
public static Stream<Path> walk(Path p) {
Stream<Path> s=Stream.of(p);
if(Files.isDirectory(p)) try {
DirectoryStream<Path> ds = Files.newDirectoryStream(p);
s=Stream.concat(s, StreamSupport.stream(ds.spliterator(), false)
.flatMap(FileTree::walk)
.onClose(()->{ try { ds.close(); } catch(IOException ex) {} }));
} catch(IOException ex) {}
return s;
}
// in case you don’t want to ignore exceprions silently
public static Stream<Path> walk(Path p, BiConsumer<Path,IOException> handler) {
Stream<Path> s=Stream.of(p);
if(Files.isDirectory(p)) try {
DirectoryStream<Path> ds = Files.newDirectoryStream(p);
s=Stream.concat(s, StreamSupport.stream(ds.spliterator(), false)
.flatMap(sub -> walk(sub, handler))
.onClose(()->{ try { ds.close(); }
catch(IOException ex) { handler.accept(p, ex); } }));
} catch(IOException ex) { handler.accept(p, ex); }
return s;
}
// and with depth limit
public static Stream<Path> walk(
Path p, int maxDepth, BiConsumer<Path,IOException> handler) {
Stream<Path> s=Stream.of(p);
if(maxDepth>0 && Files.isDirectory(p)) try {
DirectoryStream<Path> ds = Files.newDirectoryStream(p);
s=Stream.concat(s, StreamSupport.stream(ds.spliterator(), false)
.flatMap(sub -> walk(sub, maxDepth-1, handler))
.onClose(()->{ try { ds.close(); }
catch(IOException ex) { handler.accept(p, ex); } }));
} catch(IOException ex) { handler.accept(p, ex); }
return s;
}
}

关于java - 在 Java 8 流中捕获 UncheckedIOException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39558339/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com