Java 7 中 NIO.2 的使用——第四節 文件和目錄

  Files類提供了很多方法用于檢查在于你真正實際去操作一個文件或目錄。這些方法強烈推薦,也非常有用,也能避免很多異常的發生。例如,一個很好的習慣就是在你試著移動一個文件從一個地方到另一個地方的時候,先檢查文件是否存在。

  檢查一個文件或目錄是否存在

  在前面的例子中已經演示到,Path實例能夠有效的映射到一個文件或是目錄甚至這個文件或目錄物理上根本不存在。再是,Path的很多方法不會實際操作文件本身就能成功地應用。所以,事先判斷一個目錄或是文件存在就顯得非常重要。下面有兩個方法用來判斷文件是否存在。

  • exists():檢查一個文件是否存在
  • notExists(): 檢查一個文件是否不存在

  這兩個方法都包含兩個參數,第一個參數是path實例,第二個參數符號連接的文件是否處理。exist()方法返回 true如果文件存在。下下面代碼:

Path path = FileSystems.getDefault().getPath("C:/rafaelnadal/tournaments/2009","AEGON.txt");…boolean path_exists = Files.exists(path, new LinkOption[]{LinkOption.NOFOLLOW_LINKS});

  注意:!Files.exists(…)Files.notExists(…)方法不是等價的,notExists()不是exists()方法的補充。

  檢查文件的可訪問性

  一個很好的習慣就是在訪問一個文件前先檢查它的可訪問級別,可以使用isReadable(), isWritable(), isExecutable()這些方法。在傳遞一個路徑被確認后,如果文件可讀,可寫,可執行,那么虛擬機將有權限去訪問這個文件。

  另外,可以使用isRegularFile()方法在判斷文件是不是一個正常的文件。正常的文件是指沒有特別的特性(例如,不是符號鏈接,不是目錄等),包含真實的數據(例如二進制文件)。上代碼。

C:\rafaelnadal\tournaments\2009 directory (the file must exist) looks like the following:Path path = FileSystems.getDefault().getPath("C:/rafaelnadal/tournaments/2009","AEGON.txt");boolean is_readable = Files.isReadable(path);boolean is_writable = Files.isWritable(path);boolean is_executable = Files.isExecutable(path);boolean is_regular = Files.isRegularFile(path, LinkOption.NOFOLLOW_LINKS);if ((is_readable) && (is_writable) && (is_executable) && (is_regular)) {System.out.println("The checked file is accessible!");} else {System.out.println("The checked file is not accessible!");}

  或者像下面這樣的代碼:

boolean is_accessible = Files.isRegularFile(path) & Files.isReadable(path) &  Files.isExecutable(path) & Files.isWritable(path);if (is_accessible) {System.out.println("The checked file is accessible!");} else {System.out.println("The checked file is not accessible!");}

?  檢查兩個路徑是否指向同一相同文件

  在以前的章節中,有可以看到如何去檢查一個符號鏈接和目標文件是否是同一個文件。還有一個常用的測試就是你你可以使用isSameFile()方法去檢查不同的Paths的表達是否指向同一個文件。例如,一個相對路徑和一個絕對路徑可能指向同一個文件。假設有一文件的路徑為C:\rafaelnadal\tournaments\2009\MutuaMadridOpen.txt,有下面三種Path的表達方式。

Path path_1 = FileSystems.getDefault().getPath("C:/rafaelnadal/tournaments/2009","MutuaMadridOpen.txt");
Path path_2 = FileSystems.getDefault().getPath("/rafaelnadal/tournaments/2009", "MutuaMadridOpen.txt"); 
Path path_3 = FileSystems.getDefault().getPath("/rafaelnadal/tournaments/dummy/../2009", "MutuaMadridOpen.txt");try {boolean is_same_file_12 = Files.isSameFile(path_1, path_2);boolean is_same_file_13 = Files.isSameFile(path_1, path_3);boolean is_same_file_23 = Files.isSameFile(path_2, path_3);System.out.println("is same file 1&2 ? " + is_same_file_12);System.out.println("is same file 1&3 ? " + is_same_file_13);System.out.println("is same file 2&3 ? " + is_same_file_23);} catch (IOException e) {System.err.println(e);}

  輸出結果為:

is same file 1&2 ? true

is same file 1&3 ? true

is same file 2&3 ? true

  檢查文件是否可見。

  如果你需要找出一個文件是否可見,可以使用Files.isHidden()方法,需要注意的是,“hidden”這個概念是依賴平臺的。

Path path = FileSystems.getDefault().getPath("C:/rafaelnadal/tournaments/2009", "MutuaMadridOpen.txt");…try {boolean is_hidden = Files.isHidden(path);System.out.println("Is hidden ? " + is_hidden);} catch (IOException e) {System.err.println(e);}

  --------------------------------------------------------------------------------------------------------------------------------

  創建和讀取目錄

  當我們需要創建和讀取一個目錄時,NIO.2提供了一些類方法在Files類中。在這一節中,你將會發現如何列出文件系統的根,創建目錄以及臨時目錄,列出目錄里的內容,還可以對目錄進行過濾。

  列出文件系統的根目錄

  在Java 6 中,文件系統的根目錄被抽取出一個存放File對象的數組中,從Java 7 開始,NIO.2 會把根目錄作為Path對象的Iterable,通過getRootDirectories()方法返回這個Iterable接口。

Iterable<Path> dirs = FileSystems.getDefault().getRootDirectories();for (Path name : dirs) {System.out.println(name);} 

  可能的輸出結果是:

  C:\

  D:\

  E:\

  創建一個新的目錄

  直接上代碼。

Path newdir = FileSystems.getDefault().getPath("C:/rafaelnadal/tournaments/2010/");…try {Files.createDirectory(newdir);} catch (IOException e) {System.err.println(e);} 

  當然,也可以在創建目錄時設置權限信息:

Path newdir = FileSystems.getDefault().getPath("/home/rafaelnadal/tournaments/2010/");…Set<PosixFilePermission> perms = PosixFilePermissions.fromString("rwxr-x---");FileAttribute<Set<PosixFilePermission>> attr = PosixFilePermissions.asFileAttribute(perms);try {Files.createDirectory(newdir, attr);} catch (IOException e) {System.err.println(e);}

  注意,如果要創建的目錄存在,則?createDirectory()方法會拋出異常。

  有的時候,我們需要多層的目錄,例如\statistics\win\prizes,當然你可以使用createDirectory()方法,其實還可以優雅地使用Files.createDirectories()方法,

Path newdir= FileSystems.getDefault().getPath("C:/rafaelnadal/", "statistics/win/prizes");…try {Files.createDirectories(newdir);} catch (IOException e) {System.err.println(e);}

  列出目錄里的內容

Path path = Paths.get("C:/rafaelnadal/tournaments/2009");//no filter appliedSystem.out.println("\nNo filter applied:");try (DirectoryStream<Path> ds = Files.newDirectoryStream(path)) {for (Path file : ds) {System.out.println(file.getFileName());}}catch(IOException e) {System.err.println(e);}

  使用正則表達式列出目錄里的內容

Path path = Paths.get("C:/rafaelnadal/tournaments/2009");…//glob pattern appliedSystem.out.println("\nGlob pattern applied:");try (DirectoryStream<Path> ds = Files.newDirectoryStream(path, "*.{png,jpg,bmp}")) {for (Path file : ds) {System.out.println(file.getFileName());}} catch (IOException e) {System.err.println(e);}

  用戶自定義過濾器列出目錄里的內容

  如果正則表達式不能滿足你的需求,你也可以自定義自己的過濾器,這個任務很簡單,只需要繼承DirectoryStream.Filter<T>接口即可。此接口有accept()方法,一個Path是接受還是拒絕完全基于你的實現。下面的例子,只列出給定目錄下的所有目錄。

Path path = Paths.get("C:/rafaelnadal/tournaments/2009");…//user-defined filter - only directories are acceptedDirectoryStream.Filter<Path> dir_filter = new DirectoryStream.Filter<Path>() {public boolean accept(Path path) throws IOException {return (Files.isDirectory(path, NOFOLLOW_LINKS));}}; 
System.out.println("\nUser defined filter applied:");try (DirectoryStream<Path> ds = Files.newDirectoryStream(path, dir_filter)) {for (Path file : ds) {System.out.println(file.getFileName());}} catch (IOException e) {System.err.println(e);}

  還有如下自定義的過濾器。

    1.列出文件或目錄大小超過200kb的列表。

public boolean accept(Path path) throws IOException {return (Files.size(path) > 204800L);}};

    2.列出只有今天修改的文件的列表。

DirectoryStream.Filter<Path> time_filter = new DirectoryStream.Filter<Path>() {public boolean accept(Path path) throws IOException {long currentTime = FileTime.fromMillis(System.currentTimeMillis()).to(TimeUnit.DAYS);long modifiedTime = ((FileTime) Files.getAttribute(path, "basic:lastModifiedTime", NOFOLLOW_LINKS)).to(TimeUnit.DAYS);if (currentTime == modifiedTime) {return true;}return false;}};

    3.只列出隱藏的文件或目錄

DirectoryStream.Filter<Path> hidden_filter = new DirectoryStream.Filter<Path>() {public boolean accept(Path path) throws IOException {return (Files.isHidden(path));}};

  -----------------------------------------------------------------------------------------------------------------------------

?  創建,讀取和寫文件

  一個Stream表示輸入源或是輸出目的地。stream支持不同種類的數據,例如字符串,字節,基本數據類型,本地化字符還有對象。在一個無緩沖的流,每個讀或寫請求由底層操作系統直接處理,而在有緩存的流中,數據從內存中稱之為緩沖區的地方讀取,只有當緩沖區為空的時候本地輸入API會被調用。類似的,緩存的輸出流把數據寫入到緩沖區中,只有緩沖區寫滿以后本地輸出API才會被調用。當緩沖區輸出完沒有等待填滿時,外我們說這個緩沖區是清空的。

  使用標準的打開選項

  從NIO.2 開始,文件的創建,讀取和寫入操作都支持一個可選參數——OpenOption,它用來配置外面如何打開或是創建一個文件。實際上OpenOption是java.nio.file包中一個接口,它有兩個實現類:LinkOptionStandardOpenOption。下面就是選項枚舉。

READ以讀取方式打開文件
WRITE  已寫入方式打開文件
CREATE如果文件不存在,創建
CREATE_NEW如果文件不存在,創建;若存在,異常。
APPEND在文件的尾部追加
DELETE_ON_CLOSE當流關閉的時候刪除文件
TRUNCATE_EXISTING把文件設置為0字節
SPARSE文件不夠時創建新的文件
SYNC同步文件的內容和元數據信息隨著底層存儲設備
DSYNC同步文件的內容隨著底層存儲設備

?

?

?

?

?

?

?

?

?

?

?  創建一個文件

  創建文件和創建目錄類似,可以使用Files.createFile()方法,也可以在創建的時候添加權限信息。

Path newfile = FileSystems.getDefault().getPath("C:/rafaelnadal/tournaments/2010/SonyEricssonOpen.txt");…try {Files.createFile(newfile);} catch (IOException e) {System.err.println(e);}

  創建帶有權限的文件.

Path newfile = FileSystems.getDefault().getPath("/home/rafaelnadal/tournaments/2010/SonyEricssonOpen.txt");Set<PosixFilePermission> perms = PosixFilePermissions.fromString("rw-------");FileAttribute<Set<PosixFilePermission>> attr = PosixFilePermissions.asFileAttribute(perms);try {Files.createFile(newfile, attr);} catch (IOException e) {System.err.println(e);}

  寫入一個小文件

  NIO.2提供了非常優雅的方式去寫入小的二進制或是文本文件。使用Files.write()方法來創建。

  使用write()方法寫入bytes

Path ball_path = Paths.get("C:/rafaelnadal/photos", "ball.png");…byte[] ball_bytes = new byte[]{(byte)0x89,(byte)0x50,(byte)0x4e,(byte)0x47,(byte)0x0d,(byte)0x0a,(byte)0x1a,(byte)0x0a,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x0d,(byte)0x49,(byte)0x48,(byte)0x44,(byte)0x52,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x10,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x10,(byte)0x08,(byte)0x02,(byte)0x00,            …(byte)0x49,(byte)0x45,(byte)0x4e,(byte)0x44,(byte)0xae,(byte)0x42,(byte)0x60,(byte)0x82 
};try {Files.write(ball_path, ball_bytes);} catch (IOException e) {System.err.println(e);}

  按行寫入文件

Path rf_wiki_path = Paths.get("C:/rafaelnadal/wiki", "wiki.txt");…Charset charset = Charset.forName("UTF-8");ArrayList<String> lines = new ArrayList<>();lines.add("\n");lines.add("Rome Masters - 5 titles in 6 years");lines.add("Monte Carlo Masters - 7 consecutive titles (2005-2011)");lines.add("Australian Open - Winner 2009");lines.add("Roland Garros - Winner 2005-2008, 2010, 2011");lines.add("Wimbledon - Winner 2008, 2010");lines.add("US Open - Winner 2010");try {Files.write(rf_wiki_path, lines, charset, StandardOpenOption.APPEND);} catch (IOException e) {System.err.println(e);} 

?  讀取一個小文件

  NIO.2 提供了兩個方法Files.readAllBytes()?和 Files.readAllLines()方法用來讀取小的字節或是文本文件。很簡單,直接看代碼。

Path ball_path = Paths.get("C:/rafaelnadal/photos", "ball.png");…try {byte[] ballArray = Files.readAllBytes(ball_path);            } catch (IOException e) {System.out.println(e);}
Path wiki_path = Paths.get("C:/rafaelnadal/wiki", "wiki.txt");…Charset charset = Charset.forName("ISO-8859-1");try {List<String> lines = Files.readAllLines(wiki_path, charset);for (String line : lines) {System.out.println(line);}} catch (IOException e) {System.out.println(e);}

  根據官方文檔,該方法識別以下行認為是結束符:

  • \u000D followed by \u000A: 回車接著換行
  • \u000A: 換行
  • \u000D:回車

  使用緩存流進行工作

  在多數操作系統中,系統調用文件的讀寫是一件非常昂貴的操作。在緩沖的方法區和操作系統之間提供了一塊內存區域很好的解決了這個問題。

在調用本地API之前,這些方法在操作系統和應用程序之間的緩存中獲取或設置數據。這樣大大地提高了效率因為它減少了調用系統的次數。只有在緩沖區為空或是滿的時候,才會訪問硬盤,根據讀取或寫入操作。NIO.2提供了兩個通過緩存讀取和寫入文件的方法:Files.newBufferedReader()Files.newBufferedWriter(),相應的,這兩個方法會得到Path實例并返回BufferedReaderBufferedWriter 實例。

  使用?newBufferedWriter()方法

?  不多說,上代碼。

Path wiki_path = Paths.get("C:/rafaelnadal/wiki", "wiki.txt");…Charset charset = Charset.forName("UTF-8");String text = "\nVamos Rafa!";try (BufferedWriter writer = Files.newBufferedWriter(wiki_path, charset, StandardOpenOption.APPEND)) {writer.write(text);} catch (IOException e) {System.err.println(e);}

  使用newBufferedReader()方法

Path wiki_path = Paths.get("C:/rafaelnadal/wiki", "wiki.txt");…Charset charset = Charset.forName("UTF-8");try (BufferedReader reader = Files.newBufferedReader(wiki_path, charset)) {String line = null;while ((line = reader.readLine()) != null) {System.out.println(line);}} catch (IOException e) {System.err.println(e);} 

?  使用無緩存的流工作

  可以使用NIO.2直接獲取無緩存的流也可以使用java.io的API中的包裝類轉換成緩存流。使用無緩存的流的方法有Files.newInputStream()(從一個文件中讀取到輸入流中),Files.newOutputStream()方法(從輸出流中寫入到文件中)。

  使用newOutputStream() 方法

  這個方法獲取指向文件的路徑和說明文件時如何打開的,它會返回一個線程安全的無緩存的劉對象,用來寫入字節到文件中。

  上菜。

//C:\rafaelnadal\equipment\racquet.txt (the file doesn’t initially exist, but it will be automatically created because no options are specified):Path rn_racquet = Paths.get("C:/rafaelnadal/equipment", "racquet.txt");String racquet = "Racquet: Babolat AeroPro Drive GT";byte data[] = racquet.getBytes();try (OutputStream outputStream = Files.newOutputStream(rn_racquet)) {outputStream.write(data);} catch (IOException e) {System.err.println(e);}

  此外,如果你有更好的主意使用緩存的流代替上面的代碼,推薦使用基于java.io的API的轉換,正如下面的代碼,

Path rn_racquet = Paths.get("C:/rafaelnadal/equipment", "racquet.txt");String string = "\nString: Babolat RPM Blast 16";try (OutputStream outputStream = Files.newOutputStream(rn_racquet, StandardOpenOption.APPEND);BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream))) {writer.write(string);} catch (IOException e) {System.err.println(e);}

  使用?newInputStream()方法

//The following code snippet reads the content of the file racquet.txt (the file must exist):
 
Path rn_racquet = Paths.get("C:/rafaelnadal/equipment", "racquet.txt");…int n;     
try (InputStream in = Files.newInputStream(rn_racquet)) {while ((n = in.read()) != -1) {System.out.print((char)n);                }} catch (IOException e) {System.err.println(e);}

  從此而外,你也可以把一個無緩存的流轉換成緩存流,下面的代碼跟上面的代碼實現了相同的功能,但是它更加高效。

Path rn_racquet = Paths.get("C:/rafaelnadal/equipment", "racquet.txt");…try (InputStream in = Files.newInputStream(rn_racquet);BufferedReader reader = new BufferedReader(new InputStreamReader(in))) {String line = null;while ((line = reader.readLine()) != null) {System.out.println(line);}} catch (IOException e) {System.err.println(e);}

  ------------------------------------------------------------------------------------------------------------------------

?  創建臨時目錄和文件

  一個臨時目錄用來存放臨時文件。臨時目錄的存放位置依賴于操作系統。在Windows下,臨時目錄可以通過“TEMP”環境變量來設置,通常的位置是:C:\Temp, %Windows%\Temp,或者在每個用戶的:Local Settings\Temp。而Unix/Linux的臨時目錄為:/tmp/var/tmp。

  創建一個臨時目錄

  在NIO.2中通過createTempDirectory()方法用來創建一個臨時目錄,創建默認的操作系統的臨時目錄可以調用createTempDirectory()兩個參數的方法:前一個用來設置目錄的名字的前綴(可以為null),后一個可選參數用來設置文件屬性。

String tmp_dir_prefix = "nio_";try {//passing null prefixPath tmp_1 = Files.createTempDirectory(null);System.out.println("TMP: " + tmp_1.toString());//set a prefixPath tmp_2 = Files.createTempDirectory(tmp_dir_prefix);System.out.println("TMP: " + tmp_2.toString());} catch (IOException e) {System.err.println(e);} 

  則輸出結果為:

TMP: C:\Users\Leo\AppData\Local\Temp\3238630399269555448

TMP: C:\Users\Leo\AppData\Local\Temp\nio_1097550355199661257

  如果你不知道系統的默認臨時目錄的路徑,也可以使用下面的代碼:

//output: C:\Users\Leo\AppData\Local\Temp\String default_tmp = System.getProperty("java.io.tmpdir");System.out.println(default_tmp); 

  更進一步,你也可以通過createTempDirectory()方法自定義臨時目錄的路徑,

Path basedir = FileSystems.getDefault().getPath("C:/rafaelnadal/tmp/");String tmp_dir_prefix = "rafa_";try {if (Files.notExists(basedir)) {Path dir = Files.createDirectories(basedir);// create a tmp directory in the base dirPath tmp = Files.createTempDirectory(dir, tmp_dir_prefix);System.out.println("TMP: " + tmp.toString());}} catch (IOException e) {System.err.println(e);}

  輸出結果為:

TMP: C:\rafaelnadal\tmp\rafa_1753327229539718259

  使用Shutdown-Hook刪除臨時文件

  大部分操作系統都會自動地刪除臨時目錄(如果不能,你可以使用多種清理軟件),但是,有時候你需要程序級別的控制文件的刪除過程。createTempDirectory()方法只是完成了一半的工作,因為刪除工作由你負責。為了這一原因你可以shutdown-hook機制,這個機制用來執行任何資源的清理或者保持在JVM關閉之前生效。這個鉤子可以是Java線程的實現。Thread的run()方法可以在JVM關閉時執行操作。

    Figure 4-1. The simple flow design of a shutdown-hook

Runtime.getRuntime().addShutdownHook(new Thread() {@Overridepublic void run() {System.out.println("Shutdown-hook activated ...");//… here, cleanup/save resources 
System.out.println("Shutdown-hook successfully executed ...");}}); 

  shutdown-hook機制是一個很好的方法用來解決JVM關閉時刪除臨時目錄的問題。同時你也知道,如果目錄不為空的話是無法刪除的。所以你需要循環每一層目錄刪除每一個文件直至每個目錄為空再刪除目錄本身。

  使用deleteOnExit() 方法刪除臨時目錄

  另一種刪除臨時目錄的解決方法是調用deleteOnExit()方法,這個方法在java.io.Fi類中。它將在JVM關閉時刪除傳遞的文件或目錄參數。因為這個方法需要被每個目錄和文件調用,所以它最不吸引人的地方就是需要為每個臨時實體消耗內存。

  注意,如果你的系統需要長時間運行或者在很短的時間內需要創建很多文件和目錄,則使用deleteOnExit()是個很壞的主意。它需要占用大量內存即使JVM退出后還沒有釋放。

  下面演示deleteOnExit()方法的使用。

Path basedir = FileSystems.getDefault().getPath("C:/rafaelnadal/tmp/");String tmp_dir_prefix = "rafa_";try {//create a tmp directory in the base dirPath tmp_dir = Files.createTempDirectory(basedir, tmp_dir_prefix);File asFile = tmp_dir.toFile();asFile.deleteOnExit();//simulate some I/O operations over the temporary file by sleeping 10 seconds//when the time expires, the temporary file is deleted            //EACH CREATED TEMPORARY ENTRY SHOULD BE REGISTERED FOR DELETE ON EXITThread.sleep(10000);//operations done
} catch (IOException | InterruptedException e) {System.err.println(e);} 

  創建臨時文件

  不羅嗦,一些概念跟創建臨時目錄一樣,直接上代碼。

String tmp_file_prefix = "rafa_";String tmp_file_sufix=".txt";try {//passing null prefix/suffixPath tmp_1 = Files.createTempFile(null,null);System.out.println("TMP: " + tmp_1.toString());//set a prefix and a suffixPath tmp_2 = Files.createTempFile(tmp_file_prefix, tmp_file_sufix);System.out.println("TMP: " + tmp_2.toString());} catch (IOException e) {System.err.println(e);} 

  同樣,你也可以自定義臨時文件的目錄。

Path basedir = FileSystems.getDefault().getPath("C:/rafaelnadal/tmp");String tmp_file_prefix = "rafa_";String tmp_file_sufix=".txt";try {Path tmp_3 = Files.createTempFile(basedir, tmp_file_prefix, tmp_file_sufix);System.out.println("TMP: " + tmp_3.toString());} catch (IOException e) {System.err.println(e);} 

  使用?Shutdown-Hook機制刪除臨時文件

  下面代碼在C:\rafaelnadal\tmp下創建臨時文件,等待10秒鐘后,當JVM退出后刪除臨時文件。

Path basedir = FileSystems.getDefault().getPath("C:/rafaelnadal/tmp");String tmp_file_prefix = "rafa_";String tmp_file_sufix = ".txt";try {final Path tmp_file = Files.createTempFile(basedir, tmp_file_prefix, tmp_file_sufix);Runtime.getRuntime().addShutdownHook(new Thread() {@Overridepublic void run() {System.out.println("Deleting the temporary file ...");try {Files.delete(tmp_file);} catch (IOException e) {System.err.println(e);}System.out.println("Shutdown hook completed...");}});//simulate some I/O operations over the temporary file by sleeping 10 seconds//when the time expires, the temporary file is deleted            Thread.sleep(10000);//operations done
} catch (IOException | InterruptedException e) {System.err.println(e);} 

  使用?deleteOnExit() 方法刪除臨時文件

Path basedir = FileSystems.getDefault().getPath("C:/rafaelnadal/tmp");String tmp_file_prefix = "rafa_";String tmp_file_sufix = ".txt";try {final Path tmp_file = Files.createTempFile(basedir, tmp_file_prefix, tmp_file_sufix);File asFile = tmp_file.toFile();asFile.deleteOnExit();//simulate some I/O operations over the temporary file by sleeping 10 seconds//when the time expires, the temporary file is deletedThread.sleep(10000);//operations done
} catch (IOException | InterruptedException e) {System.err.println(e);} 

  使用DELETE_ON_CLOSE枚舉參數刪除臨時文件

  另一種比較獨特的刪除臨時文件的方式是使用DELETE_ON_CLOSE選項。它會在流關閉的時候刪除文件。

Path basedir = FileSystems.getDefault().getPath("C:/rafaelnadal/tmp");String tmp_file_prefix = "rafa_";String tmp_file_sufix = ".txt";Path tmp_file = null;try {tmp_file = Files.createTempFile(basedir, tmp_file_prefix, tmp_file_sufix);} catch (IOException e) {System.err.println(e);}try (OutputStream outputStream = Files.newOutputStream(tmp_file, StandardOpenOption.DELETE_ON_CLOSE);BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream))) {//simulate some I/O operations over the temporary file by sleeping 10 seconds//when the time expires, the temporary file is deleted            Thread.sleep(10000);//operations done} catch (IOException | InterruptedException e) {System.err.println(e);} 

  除此而外,你甚至不用調用createTempFile()方法,當你使用CREATE選項與DELETE_ON_CLOSE組合使用時:

String tmp_file_prefix = "rafa_";String tmp_file_sufix = ".txt";Path tmp_file = null;tmp_file = FileSystems.getDefault().getPath("C:/rafaelnadal/tmp", tmp_file_prefix + "temporary" + tmp_file_sufix);try (OutputStream outputStream = Files.newOutputStream(tmp_file, StandardOpenOption.CREATE, StandardOpenOption.DELETE_ON_CLOSE);BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream))) {//simulate some I/O operations over the temporary file by sleeping 10 seconds//when the time expires, the temporary file is deleted            Thread.sleep(10000);//operations done} catch (IOException | InterruptedException e) {System.err.println(e);} 

  目錄或文件的刪除,復制和移動

  刪除目錄或文件

  NIO.2提供了兩個用來刪除目錄或文件的方法:Files.delete()Files.deleteIfExits()。這兩個都接受單一的參數指定刪除的路徑。但是Files.delete()無返回值,Files.deleteIfExits()返回boolean值根據文件是否刪除成功。Files.delete()試圖刪除路徑下的文件或目錄,如果刪除失敗,則會拋出以下異常。NoSuchFileException (i路徑不存在), DirectoryNotEmptyException (i目錄不為空), IOException (輸入輸出錯誤發生), or SecurityException (無刪除權限)。

Path path = FileSystems.getDefault().getPath("C:/rafaelnadal/photos", "rafa_1.jpg");//delete the filetry {Files.delete(path);} catch (NoSuchFileException | DirectoryNotEmptyException | IOException | SecurityException e) {System.err.println(e);} 

  就像名字建議的一樣,Files.deleteIfExists()方法只有在文件存在的時候刪除,這就意味著如果文件不存在(代替了拋出NoSuchFileException異常)不能刪除的情況下返回boolean值false。這種應用在多線程刪除文件的時候非常有用。你不想第一個線程就拋出異常。

try {boolean success = Files.deleteIfExists(path);System.out.println("Delete status: " + success);} catch (DirectoryNotEmptyException | IOException | SecurityException e) {System.err.println(e);} 

  復制目錄或文件

  NIO.2中提供了Files.copy()方法來復制目錄和文件。它提供了StandardCopyOptionLinkOption 枚舉下的很多選項作為參數:

  • REPLACE_EXISTING: 如果目標文件存在,則替換;當拷貝符號鏈接文件時,真實文件不拷貝,值拷貝符號鏈接文件。
  • COPY_ATTRIBUTES: 拷貝文件并關聯的屬性。
  • NOFOLLOW_LINKS: 不包含符號鏈接的文件或目錄.

  這些枚舉類型靜態導入到程序中,

 import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;import static java.nio.file.StandardCopyOption.COPY_ATTRIBUTES;import static java.nio.file.LinkOption.NOFOLLOW_LINKS; 

  在兩個路徑間復制

Path copy_from = Paths.get("C:/rafaelnadal/grandslam/AustralianOpen", "draw_template.txt");Path copy_to= Paths.get("C:/rafaelnadal/grandslam/USOpen",copy_from.getFileName().toString());try {Files.copy(copy_from, copy_to, REPLACE_EXISTING, COPY_ATTRIBUTES, NOFOLLOW_LINKS);} catch (IOException e) {System.err.println(e);} 

?  從一個輸入流中拷貝到文件

Path copy_from = Paths.get("C:/rafaelnadal/grandslam/AustralianOpen", "draw_template.txt");Path copy_to = Paths.get("C:/rafaelnadal/grandslam/Wimbledon", "draw_template.txt");try (InputStream is = new FileInputStream(copy_from.toFile())) {Files.copy(is, copy_to, REPLACE_EXISTING);} catch (IOException e) {System.err.println(e);}

  文件輸入流可能來自不同的方式。例如下面的代碼中文件來自于互聯網的URL。

Path copy_to = Paths.get("C:/rafaelnadal/photos/rafa_winner_2.jpg");URI u = URI.create("https://lh6.googleusercontent.com/--udGIidomAM/Tl8KTbYd34I/AAAAAAAAAZw/j2nH24PaZyM/s800/rafa_winner.jpg");try (InputStream in = u.toURL().openStream()) {Files.copy(in, copy_to);} catch (IOException e) {System.err.println(e);}

  從一個文件拷貝到輸出流

Path copy_from = Paths.get("C:/rafaelnadal/grandslam/AustralianOpen", "draw_template.txt");Path copy_to = Paths.get("C:/rafaelnadal/grandslam/RolandGarros", "draw_template.txt");try (OutputStream os = new FileOutputStream(copy_to.toFile())) {Files.copy(copy_from, os);} catch (IOException e) {System.err.println(e);} 

  移動文件和目錄

  在這部分,你將會學習到 如何使用Files.move()方法移動目錄和文件。這個方法有一可選參數用來指定一枚舉類型:

  • REPLACE_EXISTING:若目標文件存在,則替換.
  • ATOMIC_MOVE: 執行的文件將被作為一個原子操作,保證任何過程監控文件的目錄將會訪問一個完整的文件。

  默認情況下(沒有明確指定選項) move()嘗試移動文件到目標文件,如果目標文件存在,則會失敗。除非源文件與目標文件是同一文件(isSameFile()返回 true),這種情況方法不會生效。

Path movefrom = FileSystems.getDefault().getPath("C:/rafaelnadal/rafa_2.jpg");Path moveto = FileSystems.getDefault().getPath("C:/rafaelnadal/photos/rafa_2.jpg");try {Files.move(movefrom, moveto, StandardCopyOption.REPLACE_EXISTING);} catch (IOException e) {System.err.println(e);}

  如果你不想hard-code移動文件的名字,可以使用Path.resolve()方法,通過這種方法,你可以直接從需要移動的路徑中抽取文件名字給移動文件的名字。

   Path movefrom = FileSystems.getDefault().getPath("C:/rafaelnadal/rafa_2.jpg");Path moveto_dir = FileSystems.getDefault().getPath("C:/rafaelnadal/photos");System.out.println(moveto_dir.resolve(movefrom.getFileName())); // C:\rafaelnadal\photos\rafa_2.jpgtry {Files.move(movefrom, moveto_dir.resolve(movefrom.getFileName()), StandardCopyOption.REPLACE_EXISTING);} catch (IOException e) {System.err.println(e);}

  重命名文件

  這開起來有些詭異,可以通過Files.move()Path.resolveSibling() 重命名一個文件。

Path movefrom = FileSystems.getDefault().getPath("C:/rafaelnadal/photos/rafa_2.jpg");try {Files.move(movefrom, movefrom.resolveSibling("rafa_2_renamed.jpg"), StandardCopyOption.REPLACE_EXISTING);} catch (IOException e) {System.err.println(e);}

  完。

?

?

?

?

  

  

轉載于:https://www.cnblogs.com/IcanFixIt/p/4838375.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/458815.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/458815.shtml
英文地址,請注明出處:http://en.pswp.cn/news/458815.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

計算機二級access知識點6,2019年計算機二級ACCESS考試知識點:關系數據模型

【導語】2019年計算機二級考試備考正在進行中&#xff0c;為了方便考生及時有效的備考&#xff0c;那么&#xff0c;無憂考網為您精心整理了2019年計算機二級ACCESS考試知識點&#xff1a;關系數據模型&#xff0c;歡迎大家的關注。如想獲取更多計算機二級考試的備考資料&#…

乘方取模計算(模冪計算)

乘方取模計算也稱為模冪計算&#xff0c;在密碼系統中經常使用&#xff0c;是不可缺少的。 使用本程序可以解HDU2035&#xff0c;只需要考慮輸入和輸出。 /** 乘方取模** 已知給定的正整數a、n和m&#xff0c;計算x的值&#xff0c;a^n x (mod m)。** 二分法用在這里也很有效果…

Moldflow中文版注塑流動分析案例導航視頻教程

http://item.taobao.com/item.htm?spma1z10.5.w4002-9510581626.18.30lDTO&id43054534418 QQ&#xff1a;2911984429 http://aidem.lingw.net/

Jaxb annotation使用

JAXB&#xff08;Java Architecture for XML Binding) 是一個業界的標準&#xff0c;是一項可以根據XML Schema產生Java類的技術。該過程中&#xff0c;JAXB也提供了將XML實例文檔反向生成Java對象樹的方法&#xff0c;并能將Java對象樹的內容重新寫到XML實例文檔。從另一方面來…

湖北大學計算機袁云,暑期走訪不停歇 遠赴異地送關懷——學校慰問離退休教職工和校友...

不畏酷暑送清風&#xff0c;心常為老懷關愛。7月至8月&#xff0c;正值高溫時節&#xff0c;校領導和各單位負責人根據學校黨委的安排&#xff0c;赴深圳、廣州、北京、上海等地走訪慰問70歲以上離退休教職工和部分校友&#xff0c;把學校的問候和祝福送到他們身邊。“對老同志…

MATLAB各類函數詳細講解 simulike系統仿真分析

http://item.taobao.com/item.htm?spma230r.1.14.40.yWjJFw&id43113292964&ns1&abbucket2&_uk10ekfuf6120#detail Matlab基本操作函數 SIMULINK仿真函數 插值與擬合函數視頻教程 符號運算函數視頻教程 概率統計函數視頻教程 級數與微積分函數視頻教程 矩陣運…

Github Coding Developer Book For LiuGuiLinAndroid

Github Coding Developer Book For LiuGuiLinAndroid 收集了這么多開源的PDF&#xff0c;也許會幫到一些人&#xff0c;現在里面的書籍還不是很多&#xff0c;我也在一點點的上傳&#xff0c;才上傳不到一半&#xff0c;沒辦法&#xff0c;庫存太多了 覺得全部pull麻煩的話&…

#個人博客作業week2——結對編程伙伴代碼復審

General 1.程序能夠順利地運行。程序通過命令行輸入&#xff0c;能夠向對應的文件中輸出符合要求的題目和答案。程序能夠根據用戶的不同選擇&#xff0c;進行題目的生產或答案的校驗&#xff0c;生成出的題目符合參數要求和項目的查重等各種要求&#xff0c;答案校驗準確迅速。…

Linux設備驅動程序(第三版)/深入理解計算機系統(原書第2版)/[Android系統原理及開發要點詳解].(韓超,梁泉)百度云盤下載

文檔下載云盤連接&#xff1a;http://pan.baidu.com/s/1dDD2sgT 更多其他資料&#xff0c;請關注淘寶&#xff1a;http://shop115376623.taobao.com/ http://item.taobao.com/item.htm?spma230r.1.14.3.ArS64K&id43025290175&ns1&abbucket2&_uk10ekfuf6187#d…

個人用戶上網需要有計算機電話線,個人用戶上網需要有計算機、電話線、用戶賬號和口令,以及______。...

_條形碼按照使用目的可分為()、()和()。簡述市場定位的步驟。植物、真菌、藻類和原核細胞的細胞外基質是用糞便隱血試驗鑒別消化道良性與惡性腫瘤所致的出血&#xff0c;有價值的是從長期來看,在紙幣制度下或紙幣本位下,( )是決定匯率的基礎。最常引起肺心病的疾病是從長期來看…

Xcode 5.1 編譯模擬器以及真機都能使用的靜態庫

Xcode 5.1.dmg 下載地址 http://pan.baidu.com/s/1jGJpKm6 1.新建 Framework & Library 工程 我起名叫ShowInfo,下面為其源碼 showInfo.h #import <Foundation/Foundation.h> interface ShowInfo : NSObject (void)showInfo; end showInfo.m #import "ShowI…

UVALive 6511 Term Project

Term Project Time Limit: 3000msMemory Limit: 131072KBThis problem will be judged on UVALive. Original ID: 651164-bit integer IO format: %lld Java class name: Main解題&#xff1a;強連通分量 1 #include <bits/stdc.h>2 using namespace std;3 const in…

MATLAB混合編程視頻教程下載 SIMULINK系統仿真視頻

下載鏈接&#xff1a; http://item.taobao.com/item.htm?id43401674106 精通MATLAB混合編程視頻講解 MATLAB各類函數視頻講解 基于MATLAB的高等數學問題求解 MATLAB函數速查視頻講解 面向對象C視頻教程 五朵金花&#xff0c;帶你輕松搞定MATLAB 金花詳情&#xff1a; 精通MA…

css z-index

為什么80%的碼農都做不了架構師&#xff1f;>>> css z-index 最近在發現z-index在position"relative"的元素中會失效 去掉position屬性就正常&#xff1a;z-index1 出現在 z-index999之上 記錄一下供以后查看 轉載于:https://my.oschina.net/livend/blog…

用c++寫的一個詞典工具

使用的QT圖形界面&#xff0c;用libcurl獲取的網頁&#xff0c;在之中遇見了很多問題&#xff0c;一直想用c類封裝一下libcurl,發現c很不到家啊。索性用了友元函數。 先貼上代碼吧 main.cpp #include <stdio.h> #include <stdlib.h> #include <unistd.h>#in…

VC++中Format用法

Format是一個很常用&#xff0c;卻又似乎很煩的方法&#xff0c;本人試圖對這個方法的幫助進行一些翻譯&#xff0c;讓它有一個完整的概貌&#xff0c;以供大家查詢之用&#xff1a;首先看它的聲明&#xff1a;function Format(const Format: string; const Args: array of con…

為什么NX10幫助功能無法找到HTML,NX10.0 新功能介紹視頻教程專輯

該樓層疑似違規已被系統折疊 隱藏此樓查看此樓NX10.0 新功能介紹視頻教程專輯PLM之家NX10.0界面基礎新功能--1 NX新界面增強.mp4PLM之家NX10.0界面基礎新功能--2 問題管理功能增強.mp4PLM之家NX10.0界面基礎新功能--3 資源工具條開發API接口.mp4PLM之家NX10.0界面基礎新功能--4…

SVN,桌面右擊-settings-Icon Overlays 選擇 None

SVN&#xff0c;桌面右擊->settings->Icon Overlays 選擇 None 轉載于:https://www.cnblogs.com/yu520zhong/p/4857324.html

模擬實現strstr

今天我們來模擬實現strstr這個函數&#xff0c;首先我們先來了解一下這個函數&#xff0c;這個函數原型為char *strstr(char *str1,char *str2)&#xff0c;功能是&#xff1a;從字符串str1中查找是否有符串str2&#xff0c;若str2是str1的子串&#xff0c;則先確定str2在str1的…

股票歷史數據的獲取

從 Yahoo 獲取 歷史數據 HTML Output: http://finance.yahoo.com/q/hp?s300072.sz&d7&e23&f2010&a5&b11&c2010CSV Output: http://ichart.finance.yahoo.com/table.csv?s300072.sz&d7&e23&f2010&a5&b11&c2010由于歷史原因…