2016-09-22 51 views
3

我想創建一個文件,並在之前刪除它,如果它存在。我的問題是,只要我有一個成功的刪除操作,並立即嘗試創建相同的文件夾,它與AccessDenied失敗。方法描述(對於deleteIfExists和createDirectory)都沒有提及這樣的行爲,所以我想我做錯了什麼。嘗試創建一個成功deleteIfExists後立即創建一個目錄拋出AccessDenied異常

這是代碼:

package nio2; 
import java.io.*; 
import java.nio.file.*; 
public class Test{ 

    public static void main(String[] args) 
    { 
     Path existing = Paths.get("nio2//alpha//inner.txt"); // already existing 
     Path cpytarget = Paths.get("nio2//alphacpy//inner.txt"); // file to be created 
     Path target = Paths.get("nio2//alphacpy");// 
     try{ 
      if(Files.exists(cpytarget)) 
      { 
       Files.list(target).forEach(Test::WrappedDeleteIfExists); // deleting files inside folder 
       System.out.println("Deleting the directory if it exists - alphaCpy\t" + Files.deleteIfExists(target));//deleting 
      } 
      else 
       System.out.println("It does not exist, no need to delete anything"); 
      System.out.println("Creating alphaCpy\t" + Files.createDirectory(target));//creating 
      System.out.println("copying inner.txt to the new directory\t" + Files.copy(existing,cpytarget)); 
     }catch(IOException e) 
     { 
      e.printStackTrace(); 
     } 
    } 
    public static void WrappedDeleteIfExists(Path in) 
    { 
     try{ 
      System.out.println("Deleting files inside the folder\t" + Files.deleteIfExists(in)); 
     }catch (IOException e) 
     { 
      e.printStackTrace(); 
     } 
    } 

} 

所以在成功運行(當沒有刪除)。這是輸出

It does not exist, no need to delete anything 
Creating alphaCpy  nio2\alphacpy 
copying inner.txt to the new directory nio2\alphacpy\inner.txt 

如果我以後運行它時,文件夾和文件都已經存在我得到異常:

Deleting files inside the folder  true 
Deleting the directory if it exists - alphaCpy true 
java.nio.file.AccessDeniedException: nio2\alphacpy 
     at sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:83) 
     at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:97) 
     at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:102) 
     at sun.nio.fs.WindowsFileSystemProvider.createDirectory(WindowsFileSystemProvider.java:504) 
     at java.nio.file.Files.createDirectory(Files.java:674) 
     at nio2.Test.main(Test.java:19) 

下運行是一次成功的,因爲它已經被刪除,等等。所以問題是什麼導致AccessDenied異常?請記住,該文件未打開/使用,並且相對路徑是有效的。

編輯:好吧,我設法糾正它,但老實說,我仍然無法向自己解釋最初的問題。所以我會很感激,如果有人可以幫助。我從使用流到文件[]來刪除文件夾內的文件。在我做這件事後,它就像一個魅力。

以下是更正代碼:

public static void main(String[] args) throws InterruptedException 
    { 
     Path existing = Paths.get("E:/work/Java/Tests/alpha/inner.txt"); // already existing 
     Path cpytarget = Paths.get("E:/work/Java/Tests/alphacpy/inner.txt"); // file to be created 
     Path target = Paths.get("E:/work/Java/Tests/alphacpy");// 
     File fileTarget = new File("E:/work/Java/Tests/alphacpy");  
     try{ 
      if(Files.exists(cpytarget)) 
      { 
       WrappedDeleteIfExists(fileTarget.listFiles()); // CHANGED , no longer using Stream<Path> pipeline to go through the file list 
       // deleting files inside folder 
       System.out.println("Deleting the directory if it exists - alphaCpy\t" + Files.deleteIfExists(target));//deleting 
      } 
      else 
       System.out.println("It does not exist, no need to delete anything"); 
      System.out.println(Files.exists(target)); 

      System.out.println("Creating alphaCpy\t" + Files.createDirectory(target));//creating 
      System.out.println("copying inner.txt to the new directory\t" + Files.copy(existing,cpytarget)); 
     }catch(IOException e) 
     { 
      e.printStackTrace(); 
     } 
    } 
    // CHANGED - using File[] instead of Path 
    public static void WrappedDeleteIfExists(File[] in) 
    { 
     for(int i =0;i<in.length;i++) 
     { 
      System.out.println("Deleting files inside the folder\t" +in[i].delete()); 
     } 

    } 

顯然,流操作保持它以某種方式被鎖定,即使辦完,但是這不是一個IO流(或者是它與Files.list()? ),我可以關閉,所以我能做些什麼才能使它與Stream一起工作 - 它不是可以關閉的東西,或者是試圖強制GC的東西是合理的。

+0

如果通過一行代碼在你的調試時間,你仍然可以看到相同的錯誤步驟?如果不是,刪除操作可能會在操作系統接受刪除後立即返回,但操作系統需要有限的時間(數十到數百毫秒)才能完成刪除目錄。如果是這種情況,你將不得不插入一個指數回退到1秒的重試循環。您無法無限期重試,因爲可能存在真正的拒絕訪問條件。 –

+0

調試器中的結果一步一步。還嘗試添加Thread.sleep(5000); ,這樣主線程在刪除後等待幾秒鐘。結果沒有變化。 –

+1

爲什麼你使用double _forward_斜槓。你不應該那樣做。嘗試單個正斜槓。另外,在刪除操作之後打印出'Files.exists(target)'的值,以查看NIO堆棧對目錄是否存在的看法。 –

回答

0

我注意到一個程序使用Files.list(dir)後跟Files.deleteIfExists(path)的類似問題。刪除的文件夾在Windows資源管理器視圖中都沒有消失,直到虛擬機退出爲止,並且如果在Windows資源管理器中單擊,直到虛擬機退出時爲止,會導致拒絕訪問。

我的程序只是簡單地通過在使用後關閉每個Files.list()流,最好使用try(resource)...來終止。然後,Windows資源管理器是同步與他們立刻發生,而不是等待每個刪除到VM退出

try(Stream<Path> str = Files.list(target)) 
{ 
    // do your str.forEach() calls with Files.deleteIfExists 
} 
finally 
{ 
} 
相關問題