本文是Java IO總結系列篇的第5篇,前篇的訪問地址如下:
- 總結java中創建並寫文件的5種方式-JAVA IO基礎總結第一篇
- 總結java從文件中讀取數據的6種方法-JAVA IO基礎總結第二篇
- 總結java創建文件夾的4種方法及其優缺點-JAVA IO基礎總結第三篇
- 總結java中刪除文件或文件夾的7種方法-JAVA IO基礎總結第四篇
很多朋友在看我的《java IO總結系列》之前覺得創建文件、文件夾刪除文件這些基礎操作真的是太簡單了。但看了我的文章之后,有小伙伴找到我說:“沒想到這么基礎的知識里面還有這么多的門門道道,用起來很容易,真的用好也不容易”。哪一個方法用起來簡單,哪一個方法在異常處理方面更加健壯,不看我的總結你可能還真的不知道。
有興趣的了解更多的小伙伴可以關注我,我會持續的寫這一系列的文章。如果您覺得我的文章對您有幫助,請幫忙點個贊,您的支持是我不竭的創作動力!
那我們下面就來為大家介紹本篇的內容:文件拷貝(重命名)與剪切的5種方法。首先我們來理解以下下面的幾個概念:
- 文件拷貝:將文件從一個文件夾復制到另一個文件夾
- 文件剪切:將文件從當前文件夾,移動到另一個文件夾
- 文件重命名:將文件在當前文件夾下面改名(也可以理解為將文件剪切為當前文件夾下面的另一個文件)
一、文件拷貝
傳統IO中的文件copy的方法,使用輸入輸出流,實際上就是重新創建並寫入一個文件。如果目標文件已經存在,就覆蓋掉它,重新創建一個文件並寫入數據。這種方式不夠友好,覆蓋掉原有文件沒有給出任何提示,有可能導致原有數據的丟失。
@Test
void testCopyFile1() throws IOException {
File fromFile = new File("D:\\data\\test\\newFile.txt");
File toFile = new File("D:\\data\\test2\\copyedFile.txt");
try(InputStream inStream = new FileInputStream(fromFile);
OutputStream outStream = new FileOutputStream(toFile);) {
byte[] buffer = new byte[1024];
int length;
while ((length = inStream.read(buffer)) > 0) {
outStream.write(buffer, 0, length);
outStream.flush();
}
}
}
Java NIO中文件copy的方法,使用方式簡單。當目標文件已經存在的時候會拋出FileAlreadyExistsException ,當源文件不存在的時候拋出NoSuchFileException,針對不同的異常場景給出不同的Exception,更有利於我們寫出健壯性更好的程序。
@Test
void testCopyFile2() throws IOException {
Path fromFile = Paths.get("D:\\data\\test\\newFile.txt");
Path toFile = Paths.get("D:\\data\\test2\\copyedFile.txt");
Files.copy(fromFile, toFile);
}
如果在目標文件已經存在的情況下,你不想拋出FileAlreadyExistsException ,而是去覆蓋它,也可以靈活的選擇使用下面的選項
- StandardCopyOption.REPLACE_EXISTING 來忽略文件已經存在的異常,如果存在就去覆蓋掉它
//如果目標文件存在就替換它
Files.copy(fromFile, toFile, StandardCopyOption.REPLACE_EXISTING);
- StandardCopyOption.COPY_ATTRIBUTES copy文件的屬性,最近修改時間,最近訪問時間等信息,不僅copy文件的內容,連文件附帶的屬性一並復制
CopyOption[] options = { StandardCopyOption.REPLACE_EXISTING,
StandardCopyOption.COPY_ATTRIBUTES //copy文件的屬性,最近修改時間,最近訪問時間等
};
Files.copy(fromFile, toFile, options);
二、文件重命名
NIO中可以使用Files.move方法在同一個文件夾內移動文件,並更換名字。當目標文件已經存在的時候,同樣會有FileAlreadyExistsException,也同樣可以使用StandardCopyOption去處理該異常。
@Test
void testRenameFile() throws IOException {
Path source = Paths.get("D:\\data\\test\\newFile.txt");
Path target = Paths.get("D:\\data\\test\\renameFile.txt");
//REPLACE_EXISTING文件存在就替換它
Files.move(source, target,StandardCopyOption.REPLACE_EXISTING);
}
下文中的實現方法和上面代碼的效果是一樣的,resolveSibling作用是將source文件的父路徑與參數文件名合並為一個新的文件路徑。
resolve系列函數在windows和linux等各種系統處理路徑分隔符號、路徑與文件名合並等,比自己手寫代碼去處理不同操作系統的路徑分隔符號、路徑與文件名合並有更好的操作系統兼容性。
@Test
void testRenameFile2() throws IOException {
Path source = Paths.get("D:\\data\\test\\newFile.txt");
//這種寫法就更加簡單,兼容性更好
Files.move(source, source.resolveSibling("renameFile.txt"));
}
傳統IO中使用File類的renameTo方法重命名,失敗了就返回false,沒有任何異常拋出。你不會知道你失敗的原因是什么,是因為源文件不存在導致失敗?還是因為目標文件已經存在導致失敗?所以這種方法筆者不建議使用。
@Test
void testRenameFile3() throws IOException {
File source = new File("D:\\data\\test\\newFile.txt");
boolean succeeded = source.renameTo(new File("D:\\data\\test\\renameFile.txt"));
System.out.println(succeeded); //失敗了false,沒有異常
}
三、文件剪切
文件剪切實際上仍然是Files.move,如果move的目標文件夾不存在或源文件不存在,都會拋出NoSuchFileException
@Test
void testMoveFile() throws IOException {
Path fromFile = Paths.get("D:\\data\\test\\newFile.txt"); //文件
Path anotherDir = Paths.get("D:\\data\\test\\anotherDir"); //目標文件夾
Files.createDirectories(anotherDir);
Files.move(fromFile, anotherDir.resolve(fromFile.getFileName()),
StandardCopyOption.REPLACE_EXISTING);
}
resolve函數是解析anotherDir路徑與參數文件名進行合並為一個新的文件路徑。
歡迎關注我的博客,里面有很多精品合集
- 本文轉載注明出處(必須帶連接,不能只轉文字):字母哥博客。
覺得對您有幫助的話,幫我點贊、分享!您的支持是我不竭的創作動力! 。另外,筆者最近一段時間輸出了如下的精品內容,期待您的關注。