2016-09-18 3 views
2

EDIT : 이것은 가능하지 않습니다. https://bugs.openjdk.java.net/browse/JDK-8039910을 참조하십시오.Java 8 스트림에서 UncheckedIOException을 catch하십시오.

나는 Stream<Path>을 제공하는 도우미 클래스가 있습니다. 이 코드는 Files.walk 래핑 출력 정렬 : 심볼릭 링크가 따른다

public Stream<Path> getPaths(Path path) { 
    return Files.walk(path, FOLLOW_LINKS).sorted(); 
} 

같이, 파일 시스템 (예를 들어, 심볼릭 x -> .) Files.walk에 사용되는 코드의 루프의 경우 FileSystemLoopException 인스턴스를 감싸는 UncheckedIOException을 던진다.

내 코드에서 이러한 예외를 잡아 내고 싶습니다. 예를 들어 유용한 메시지를 기록하십시오. 결과 스트림은 이러한 상황이 발생하자마자 항목 제공을 중단 할 수 있습니다.

코드에 .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; 
    } 
} 

방법, 모든 경우에, 나는 경로의 소비자가이 예외가 발생하지 않도록하는 Stream<Path>을주고 내 코드에 UncheckedIOException를 잡을 수 있습니까? 예를 들어

가, 다음 코드는 예외가 발생해서는 안 :

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 ... 
: 지금

List<Path> paths = getPaths().collect(toList()); 

를 제외하고는 코드가 collect를 호출 (그리고 내가 거기에 예외를 잡을 수있다)에 의해 트리거됩니다


편집 : 간단한 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(); 
     } 
    } 
} 
+2

는 http://stackoverflow.com/q/22867286/4856258에 중복 같은데. 요약하면'Files.walk'를 사용하여이 작업을 할 수 없으며,이를 위해 완전히 독립적 인 메소드를 작성하거나 제 3 자 라이브러리를 사용해야합니다. –

+0

나는 completablefuture.suppltasync에 그 방법을 넣고 그 예외를 잡기 위해 excepcetionaly를 추가합니까? – gaston

+0

나는 당신이 말하는 것을 이해하지 못합니다, @ 가스통. –

답변

1

당신은 당신의 자신의 도보 스트림 공장을 만들 수 있습니다

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; 
    } 
} 
관련 문제