>

필요한 것은 폴더 이름 패턴을 기반으로 하위 폴더 (모든 레벨에서) 및 해당 컨텐츠를 식별하고 삭제하기 위해 일련의 폴더를 순회하는 것입니다. Java 7의 방문자 클래스를 사용하여 작업 코드를 가지고 있지만 Java 8 스트림에서 작동하도록하려고합니다.

일하는 코드를 만들었지 만 (아래 참조), 반복하지 않고 더 좋고 더 간단한 방법을 사용해야한다는 인상을 받았습니다.

 public void delete(List<Path> folders) {
     folders
     .stream()
     .filter(Files::isDirectory)
     .forEach(this::evaluateIfTrash);
  }
  private void evaluateIfTrash(Path folder) {
    try (Stream<Path> dir = Files.walk(folder, FileVisitOption.FOLLOW_LINKS)) {
      dir.filter(Files::isDirectory)
          .filter(TrashPredicate::isTrashFolder)
          .forEach(this::recursivelyDelete);
    } catch (IOException e) {
      log.error("Failed to evaluate {}", folder, e);
    }
  }
  private void recursivelyDelete(Path folder) {
    try (Stream<Path> dir = Files.walk(folder, FileVisitOption.FOLLOW_LINKS)) {
      dir.sorted(Comparator.reverseOrder())
          .map(Path::toFile)
          .filter(File::exists)
          .forEach(File::delete);
    } catch (IOException e) {
      log.error("Failed to delete {}", folder, e);
    }
  }

여기에서 몇 가지 문서와 몇 가지 답변을 읽은 후 중복 스트림을 제거하는 방법으로 중첩 스트림을 시도했습니다.

private void delete(List<Path> folders) {
    folders
    .stream()
    .filter(Files::isDirectory)
    .flatMap(
        f -> {
          try {
            return Files.walk(f, FileVisitOption.FOLLOW_LINKS);
          } catch (IOException e) {
            return Stream.empty();
          }
        })
    .filter(TrashPredicate::isTrashFolder)
    .forEach(this::recursivelyDelete);
  }
private void recursivelyDelete(Path folder) {
    try (Stream<Path> dir = Files.walk(folder, FileVisitOption.FOLLOW_LINKS)) {
      dir.sorted(Comparator.reverseOrder())
          .map(Path::toFile)
          .filter(File::exists)
          .forEach(File::delete);
    } catch (IOException e) {
      log.error("Failed to delete {}", folder, e);
    }
  }

이 방법은 (가독성이 좋지 않은 경우에도) 메소드 중 하나를 제거하지만 실제로 내가 싫어하는 것은 flatMap 연산에 의해 반환 된 내부 스트림을 닫지 않는다는 사실입니다. 리소스를 사용하여 try-with-resource 구문을 사용하고 필터 내에서 forEach 작업을 이동하여 시도하면 스트림이 이미 닫혀 있고 추가 작업에 사용할 수 없다는 오류가 표시됩니다.

지난 2 일 동안이 작업을 성공시키지 않고 노력해 왔기 때문에 다시 질문은 Java 8을 사용하여이 작업을 수행하는 더 나은 (깨끗한) 방법이 있습니까?


  • 답변 # 1

    Files.walk는 루트 경로를 재귀 적으로 먼저 먼저 스트리밍합니다. 아파치 커먼즈의 FileUtils에는 deleteDirectory가있어 디렉토리를 재귀 적으로 제거하여 코드를 매우 깨끗하게 만듭니다.

    아래와 같은 것이 작동해야합니다

           Files.walk(rootPath)
                .filter(Files::isDirectory).
                .filter(TrashPredicate::isTrashFolder)
                .forEach(FileUtils::deleteDirectory);
    
    

  • 이전 string - Ruby 스크립트 내부의 Ruby 내부 편집
  • 다음 c++ - 속성이있는 요소의 XML GetText