2015-12-05 30 views
0

我想复制文件并替换现有文件。问题是,如果该文件正在被另一个程序使用,则会发生AccessDeniedException,并且现有文件被删除。如果复制失败,我希望保留现有文件。下面的代码演示了这个问题。 (注意:另据报道在Java Files.copy replace existing deletes file entirely这个问题,但OP没有提供一种方式来重现问题。)Java Files.copy在访问被拒绝时删除文件

public void copyFile(){ 

    Path workingCopy = null; 

    //Create a plain text file called example-file-error.txt, add some text to the file, and save it in user.home 
    Path path = Paths.get(System.getProperty("user.home"), "example-file-error.txt"); 

    try{ 
     workingCopy = Files.createTempFile(path.getParent(), "temp", ".txt"); 

     //Create a locked file, but the lock is actually created by a separate program 
     FileChannel fileChannel = FileChannel.open(path, StandardOpenOption.READ); 
     FileLock lock = fileChannel.lock(0, Long.MAX_VALUE, true); 

     Files.copy(workingCopy, path, StandardCopyOption.REPLACE_EXISTING); 

    }catch(Exception ex){ 
     ex.printStackTrace(); 
    }finally{ 
     try{ 
      Files.deleteIfExists(workingCopy); 
     }catch(IOException ex){ 
      ex.printStackTrace(); 
     } 

    } 

} 

有没有一种方式,如果拷贝没有保留原来的文件吗?或者,有没有办法在尝试复制之前等待访问文件?

回答

0

删除此行Files.deleteIfExists(workingCopy);从最后并把它放在try子句

public void copyFile() { 
Path workingCopy = null; //Create a plain text file called example-file-error.txt, add some text to the file, and save it in user.home 
Path path = Paths.get(System.getProperty("user.home"), "example-file-error.txt"); 
try{ 
workingCopy = Files.createTempFile(path.getParent(), "temp", ".txt"); //Create a locked file, but the lock is actually created by a separate program 
FileChannel fileChannel = FileChannel.open(path, StandardOpenOption.READ); 
FileLock lock = fileChannel.lock(0, Long.MAX_VALUE, true); 
Files.copy(workingCopy, path, StandardCopyOption.REPLACE_EXISTING); 
Files.deleteIfExists(workingCopy); 

    }catch(Exception ex) 
{ ex.printStackTrace(); } 
+0

这并不能解决问题。现有文件仍然被删除,但临时文件被保留。 – meyerjp3

0

的解决方案是使用Files.move()代替Files.copy()的选项StandardCopyOption结束。 REPLACE_EXISTING和StandardCopyOption.ATOMIC_MOVE。原子移动可防止在发生异常时删除目标文件。该解决方案适用于Windows 10,但原子移动无法保证适用于所有操作系统。我不确定哪些不允许这个选项。解决方案如下。

public void copyFile(){ 

    Path workingCopy = null; 

    //Create a plain text file called example-file-error.txt, add some text to the file, and save it in user.home 
    Path path = Paths.get(System.getProperty("user.home"), "example-file-error.txt"); 

    try{ 
     workingCopy = Files.createTempFile(path.getParent(), "temp", ".txt"); 

     //Create a locked file, but the lock is actually created by a separate program 
     FileChannel fileChannel = FileChannel.open(path, StandardOpenOption.READ); 
     FileLock lock = fileChannel.lock(0, Long.MAX_VALUE, true); 

     //This line seems to be the solution to the problem 
     Files.move(workingCopy, path, StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.ATOMIC_MOVE); 

    }catch(IOException ex){ 
     ex.printStackTrace(); 
    }finally{ 
     try{ 
      Files.deleteIfExists(workingCopy); 
     }catch(IOException ex){ 
      ex.printStackTrace(); 
     } 

    } 

}