2016-01-25 5 views
0

Я видел много примеров того, как рекурсивно копировать или удалять файлы с помощью Java NIO.2. Например, копирование папки со всем ее содержимым:Перемещение не пустой директории рекурсивно с использованием Java NIO.2 FileVisitor и Files.walkFileTree (...)

/** 
* Copies a folder with all contents recursively. Class implements 
* {@code FileVisitor} interface. 
* @author Ernestas Gruodis 
*/ 
public static class TreeCopy implements FileVisitor<Path> { 

     private final Path source; 
     private final Path target; 
     private final boolean replace; 
     private final CopyOption[] options; 
     private final ArrayList<Object[]> events = new ArrayList<>(); 

     /** 
     * Copies a folder with all contents recursively. 
     * 
     * @param source source file path. 
     * @param target target file path. 
     * @param replace {@code true} if existing file should be replaced. 
     */ 
     public TreeCopy(Path source, Path target, boolean replace) { 
      this.source = source; 
      this.target = target; 
      this.replace = replace; 

      options = replace ? new CopyOption[]{COPY_ATTRIBUTES, REPLACE_EXISTING} : new CopyOption[0]; 
     } 

     @Override 
     public synchronized FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) { 

      Path newDir = target.resolve(source.relativize(dir)); 
      try { 
       Files.copy(dir, newDir, options); 
      } catch (FileAlreadyExistsException ex) { 
       if (!replace) { 
        events.add(new Object[]{"Folder already exists", newDir, ex}); 
        return FileVisitResult.TERMINATE; 
       } else { 
        return FileVisitResult.CONTINUE; 
       } 
      } catch (DirectoryNotEmptyException ex) { 
       //Ignore 
      } catch (IOException ex) { 
       events.add(new Object[]{"Unable to create a folder", newDir, ex}); 
       return FileVisitResult.SKIP_SUBTREE; 
      } 
      return FileVisitResult.CONTINUE; 
     } 

     @Override 
     public synchronized FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { 

      Path newFile = target.resolve(source.relativize(file)); 
      try { 
       Files.copy(file, newFile, options); 
      } catch (FileAlreadyExistsException ex) { 
       events.add(new Object[]{"File already exists", newFile, ex}); 
      } catch (NoSuchFileException ex) { 
       events.add(new Object[]{"No such file", newFile.getParent(), ex}); 
      } catch (IOException ex) { 
       events.add(new Object[]{"Unable to create a file", newFile, ex}); 
      } 
      return FileVisitResult.CONTINUE; 
     } 

     @Override 
     public synchronized FileVisitResult postVisitDirectory(Path dir, IOException exc) { 

      if (exc == null) { 
       Path newDir = target.resolve(source.relativize(dir)); 
       try { 
        FileTime time = Files.getLastModifiedTime(dir); 
        Files.setLastModifiedTime(newDir, time); 
       } catch (IOException ex) { 
        events.add(new Object[]{"Unable to copy all attributes to", newDir, ex}); 
       } 
      } 
      return FileVisitResult.CONTINUE; 
     } 

     @Override 
     public synchronized FileVisitResult visitFileFailed(Path file, IOException ex) { 

      if (ex instanceof FileSystemLoopException) { 
       events.add(new Object[]{"Cycle detected", file, ex}); 
      } else { 
       events.add(new Object[]{"Unable to copy", file, ex}); 
      } 
      return FileVisitResult.CONTINUE; 
     } 

     /** 
     * Returns errors which happened while copying a directory. 
     * 
     * @return {@code ArrayList<Object[]>} error list, where at each entry 
     * of {@code Object[]} index: 
     * <ul><li> 0 - {@code String} - error description; 
     * </li><li> 1 - {@code Path} - target folder/file path; 
     * </li><li> 2 - {@code Exception} - specific exception. 
     * </li></ul> 
     */ 
     public ArrayList<Object[]> getEvents() { 

      return events; 
     } 
    } 


Path source = Paths.get("/toCopyDir"), 
    target = Paths.get("/someDir2/etc/toCopyDir"); 

EnumSet<FileVisitOption> opts = EnumSet.of(FileVisitOption.FOLLOW_LINKS); 
TreeCopy tc = new TreeCopy(source, target, true); 
try { 
    Files.walkFileTree(source, opts, Integer.MAX_VALUE, tc); 
} catch (IOException ex) { 
    //Handle exception 
} 

Но как переместить папку, содержащую файлы? Существует метод Files.move(Path source, Path target, CopyOption... options) throws IOException. Может ли кто-нибудь дать реальный эффективный пример?

Я думаю, что решение может быть использование Files.copy(...) в preVisitDirectory(...), а затем Files.delete(...) в postVisitDirectory(...), что-то подобное ..

+0

Files.move (новый файл («/ path/to/srcFolder»). ToPath(), новый файл («/ path/to/dstFolder»). ToPath(), StandardCopyOption.ATOMIC_MOVE); работает для меня – guleryuz

+0

И даже если каталог не пуст? –

+0

Я думаю, что с помощью 'FileVisitor' вы можете добиться большего контроля. Я сделал это с помощью 'Files.copy (...)' в 'preVisitDirectory (...)', а затем 'Files.delete (...)' в 'postVisitDirectory (...)'. Но до сих пор не знаю, возможно ли использовать 'Files.move (...)' вместе с 'FileVisitor', возможно, нет .. только для одиночных файлов и пустых папок. –

ответ

-1

Это link поможет. Пожалуйста, просмотрите документ.