1 總述
Commons IO
(Apache Commons IO)是一個廣泛用於 Java 開發的開源工具庫,由Apache
軟體基金會維護和支援。這個庫旨在簡化檔案和流操作,提供了各種實用工具類和方法,以便更輕鬆地進行輸入輸出操作。以下是 Commons IO 的一些主要特點和功能:
- 檔案操作:Commons IO 提供了大量用於檔案和目錄操作的方法,包括建立、刪除、重新命名、複製、移動檔案,以及遞迴地操作目錄結構。
- 流處理:你可以使用 Commons IO 處理各種輸入和輸出流,包括讀取、寫入和操作流資料。這對於處理文字檔案、二進位制檔案以及網路通訊非常有用。
- 檔案過濾和篩選:Commons IO 允許你輕鬆地篩選檔案和目錄,根據各種條件,如副檔名、檔案大小、最後修改時間等。
- 檔案內容操作:你可以比較兩個檔案的內容,查詢檔案中的文字,以及進行替換等操作。
- 自動關閉流:Commons IO 提供了自動關閉流的功能,確保在處理檔案和流時,資源得以正確釋放,而無需顯式呼叫close()方法。
- 異常處理:庫中的方法通常會處理 I/O 異常,以簡化程式碼中的錯誤處理。
- 效能和可靠性:Commons IO 被廣泛使用,因為它經過了精心設計,以提供高效能和可靠性。這對於處理大型檔案和在生產環境中執行的應用程式非常重要。
它可以顯著簡化日常的 I/O 任務,減少了編寫重複性程式碼的需要,提高了開發效率。如果你是 Java 開發者,特別是在處理檔案和流方面,建議考慮使用 Commons IO 來簡化你的工作。你可以在 Apache Commons IO 的官方網站上找到詳細的文件和示例程式碼,以瞭解如何使用這個庫。
- dependency import
commons.io.version
:1.11.0
<!-- https://commons.apache.org/proper/commons-io/ -->
<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons.io.version}</version>
<scope>provided</scope>
</dependency>
如下座標已廢止、不建議使用:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-io</artifactId>
<version>1.3.2</version>
</dependency>
- 核心工具類 :
org.apache.commons.io.FilenameUtils
@Test
public void test(){
//String filePath = FilenameUtils.concat("/base-dir/", "/demo-file.txt");//[x] 錯誤示範 , out : /demo-file.txt String filePath = FilenameUtils.concat("/base-dir/", "demo-file.txt");// out : \\base-dir\\demo-file.txt
log.info("filePath : {}", filePath);//filePath : \\base-dir\\demo-file.txt
Boolean equalsResult = FilenameUtils.equals("/base-dir/a", "/base-dir/b");
log.info("equalsResult : {}", equalsResult);//equalsResult : false
}
- 核心工具類 :
org.apache.commons.io.FileUtils
- 核心工具類 :
org.apache.commons.io.IOUtils
- 核心工具類 :
org.apache.commons.io.file.PathUtils
2 核心方法
遞迴列出目錄中的檔案和子目錄
File directory = new File("parentDir");
Collection<File> allFilesAndDirs = FileUtils.listFilesAndDirs(directory, TrueFileFilter.INSTANCE, TrueFileFilter.INSTANCE);
用於遞迴列出目錄中的所有檔案和子目錄。
列出目錄中的檔案
File directory = new File("directory");
String[] filesInDir = directory.list();
用於獲取指定目錄中的檔案和子目錄的名稱列表。
查詢檔案
用於在目錄中查詢檔案,並將結果作為檔案物件的集合返回。
File searchDir = new File("searchDir");
Collection<File> foundFiles = FileUtils.listFiles(searchDir, TrueFileFilter.TRUE, TrueFileFilter.TRUE);
獲取臨時目錄、使用者主目錄
- getTempDirectoryPath :用於獲取作業系統的臨時目錄。
- getUserDirectoryPath :使用者獲取使用者主目錄
- 通常是使用者檔案的根目錄。
String tempDirectoryPath = FileUtils.getTempDirectoryPath();// C:\\Users\\xxxx\\AppData\\Local\\Temp\\
//File tempDirectory = FileUtils.getTempDirectory();//獲取臨時目錄 的 File 物件
String userDirectoryPath = FileUtils.getUserDirectoryPath();// C:\\Users\\xx
//File userDirectory = FileUtils.getUserDirectory();//獲取使用者主目錄 的 File 物件
建立目錄
用於建立目錄,包括建立任何中間目錄(如果它們不存在)。
File newDir = new File("newDir");
FileUtils.forceMkdir(newDir);
建立臨時目錄
File tempDir = File.createTempFile("tempDir", "");
tempDir.delete(); // 刪除檔案,使其成為目錄
刪除目錄
//刪除目錄或檔案,無法刪除會拋異常
FileUtils.deleteDirectory(new File("D://test/test1"));//遞迴刪除目錄
//deleteQuietly => 安靜刪除目錄或檔案,無法刪除時也不會拋異常
FileUtils.deleteQuietly(new File("D://test/test1"));//如果是目錄,會級聯刪除;不會丟擲異常,安靜刪除
獲取作業系統檔案分隔符
用於獲取作業系統的檔案分隔符,例如,在 Windows 中是反斜槓(\
),在 Unix/Linux 中是正斜槓(/
)。
File file = new File("hiddenFile.txt");
boolean isHidden = file.isHidden();
建立臨時檔案
用於建立一個臨時檔案,通常在操作完成後會被自動刪除。
File tempFile = File.createTempFile("temp", ".txt");
獲取臨時資料夾的路徑
用於獲取作業系統的臨時資料夾路徑。
String tempDirPath = System.getProperty("java.io.tmpdir");//C:\\Users\\xx\\AppData\\Local\\Temp\\
獲取指定檔案
//獲取指定路徑下的檔案
File file = FileUtils.getFile("D://test/test-dir/123.txt");
File file = FileUtils.getFile("log4j2.properties");// file.getCanonicalPath() : //E:\source_code\XXX\xxx-bigdata\xxx-common-utils\log4j2.properties
//獲取指定目錄下的檔案
File file1 = FileUtils.getFile(new File("D://test/test-dir"), "123.txt", "456.txt");
獲取檔案,等待指定時長至其存在
//等待一個檔案xx秒,知道檔案建立後才返回。每max(100,remainning)迴圈檢查一次
while (FileUtils.waitFor(new File("D://test/test1"), 60)) {
//...
}
建立檔案
建立檔案,如果檔案存在則更新時間;如果不存在,建立一個空檔案
FileUtils.touch(new File("D://test/test4"));
複製檔案
File source = new File("source.txt");
File destination = new File("destination.txt");
FileUtils.copyFile(source, destination);
//案例:將b資料夾下a.doc複製到mm下a.doc,前者不存在會報錯,後者不存在會新建;如果後者存在同名檔案則替換
//FileUtils.copyFile(new File("d:/b/a.doc"), new File("d:/b/mm/a.doc"));
//FileUtils.copyFile(new File("d:/b/a.doc"), new File("d:/b/mm","a.doc"));//與上一方式等效
檔案複製,但保留原檔案的屬性
用於複製檔案,保留原檔案的屬性,如許可權和時間戳。
File source = new File("source.txt");
File destination = new File("destination.txt");
FileUtils.copyFile(source, destination, true);
刪除檔案(強制)
這個方法用於強制刪除一個檔案,即使它是隻讀的或不存在。
File fileToDelete = new File("fileToDelete.txt");
FileUtils.forceDelete(fileToDelete);
刪除檔案(在JVM程式退出執行時,強制)
//當JVM退出時,把file物件刪除。如果是目錄物件則遞迴刪除子目錄,跟delete的區別是一個是立馬執行 一個是JVM退出後執行 forceDeleteOnExit 這個用來刪除臨時檔案或快取檔案用的
try {
File file2 = new File("C:\\Users\\Administrator\\Desktop\\sign\\");
FileUtils.forceDeleteOnExit(file2);
} catch (Exception e) {
e.printStackTrace();
}
遞迴刪除目錄下的指定檔案
//用於遞迴刪除指定檔名的檔案
File directory = new File("parentDir");
String fileNameToDelete = "fileToDelete.txt";
FileFilter fileFilter = new NameFileFilter(fileNameToDelete);
Collection<File> foundFiles = FileUtils.listFiles(directory, fileFilter, TrueFileFilter.TRUE);
for (File fileToDelete : foundFiles) {
FileUtils.forceDelete(fileToDelete);
}
移動檔案
用於將檔案從一個位置移動到另一個位置。
File oldFile = new File("oldFile.txt");
File newFile = new File("newFile.txt");
FileUtils.moveFile(oldFile, newFile);
檔案重新命名
File oldFile = new File("oldName.txt");
File newFile = new File("newName.txt");
FileUtils.moveFile(oldFile, newFile);
複製資料夾
String filePath1 = "D://test/test1" ;
File srcDir = new File( filePath1 ) ;
String filePath2 = "D://test/test2" ;
File destDir = new File( filePath2 ) ;
try {
//方式1: 複製資料夾(資料夾裡面的檔案內容也會複製)
FileUtils.copyDirectory(srcDir, destDir);
//方式2: 僅僅複製目錄↓ (複製資料夾,帶有檔案過濾功能)
//FileUtils.copyDirectory(srcDir, destDir, DirectoryFileFilter.DIRECTORY);
//IOFileFilter txtSuffixFilter = FileFilterUtils.suffixFileFilter(".txt");// 建立.txt過濾器
//IOFileFilter txtFiles = FileFilterUtils.andFileFilter(FileFileFilter.FILE, txtSuffixFilter);
// 建立包含目錄或者txt檔案的過濾器
//FileFilter filter = FileFilterUtils.orFileFilter(DirectoryFileFilter.DIRECTORY, txtFiles);
// Copy using the filter
//FileUtils.copyDirectory(srcDir, destDir, filter);//TODO 閱讀doCopyDirectory原始碼
//方式3: 將目錄1所有的資料夾及檔案複製到目錄2下,如果有同名資料夾則合併,如果有同名檔案則替換
//FileUtils.copyDirectoryToDirectory(srcDir, destDir);
} catch (IOException e) {
e.printStackTrace();
}
複製檔案到指定資料夾下
FileUtils.copyFileToDirectory(
new File("C://Users/xx/Desktop/newDir/123/123.txt"),
new File("C://Users/xx/Desktop/newDir/456")
);
遞迴複製檔案
這個方法將遞迴地複製一個目錄及其所有內容到目標目錄。
File sourceDir = new File("sourceDir");
File destDir = new File("destDir");
FileUtils.copyDirectory(sourceDir, destDir);
遞迴刪除檔案
File directoryToDelete = new File("directoryToDelete");
FileUtils.deleteDirectory(directoryToDelete);
刪除目錄中的檔案
用於刪除目錄中的所有檔案,但保留目錄結構。
//清除目錄中的內容,不會刪除該目錄, 遍歷目錄中的檔案。
//如果是目錄,則遞迴刪除;如果是檔案,則強制刪除;刪除失敗(檔案不存在或無法刪除)都會丟擲異常
File directory = new File("dirToDelete");
FileUtils.cleanDirectory(directory);
檔案內容替換
File file = new File("file.txt");
String oldText = "replaceThis";
String newText = "withThis";
String replacedText = FileUtils.readFileToString(file, "UTF-8");
replacedText = StringUtils.replace(replacedText, oldText, newText);
FileUtils.writeStringToFile(file, replacedText, "UTF-8");
獲取檔案大小
File file = new File("file.txt");
long fileSize = FileUtils.sizeOf(file);//返回 Long
FileUtils.sizeOfAsBigInteger(file);//返回 BigInteger
獲取檔案的大小的可讀表示
用於將檔案大小以位元組表示轉換為易讀的格式,例如 "2.5 MB"。
EB, PB, TB, GB, MB, KB or bytes
File file = new File("file.txt");
String readableSize = FileUtils.byteCountToDisplaySize(file.length());
獲取檔案的副檔名(不包括點號)
用於獲取檔案的副檔名,不包括點號,例如,對於 "example.txt",將返回 "txt"。
String fileName = "example.txt";
String extension = FilenameUtils.getExtension(fileName);//txt
判斷檔案是否是隱藏檔案
File file = new File("hiddenFile.txt");
boolean isHidden = file.isHidden();
判斷是否為符號連結檔案
FileUtils.isSymlink(new File("D://test/test1"));
檢查檔案是否可寫
File file = new File("writableFile.txt");
boolean isWritable = file.canWrite();
比較檔案內容
用於比較兩個檔案的內容是否相同。
File file1 = new File("file1.txt");
File file2 = new File("file2.txt");
boolean contentEqual = FileUtils.contentEquals(file1, file2);
//FileUtils.contentEqualsIgnoreEOL(new File("D://test/test1"), new File("D://test/test2"), null);//忽略換行符,第3個引數是字符集
比較目錄結構
用於比較兩個目錄的內容是否相同,忽略不同作業系統的換行符。
File dir1 = new File("directory1");
File dir2 = new File("directory2");
boolean isSame = FileUtils.contentEqualsIgnoreEOL(dir1, dir2, "UTF-8");
讀取 URL 內容到字串
String urlContent = IOUtils.toString(new URL("https://baidu.com"));
/**
urlContent :
<html>
<head><title>302 Found</title></head>
<body bgcolor="white">
<center><h1>302 Found</h1></center>
<hr><center>bfe/1.0.8.18</center>
</body>
</html>
**/
寫入字串到 URL
用於將字串寫入 URL。
URL url = new URL("https://example.com");
String content = "Hello, World!";
IOUtils.write(content, url.openConnection().getOutputStream(), "UTF-8");
逐行讀取檔案內容(返回迭代器)
用於逐行讀取檔案內容,避免一次性載入整個檔案。
File file = new File("file.txt");
LineIterator lines = FileUtils.lineIterator(file, "UTF-8");
while (lines.hasNext()) {
String line = lines.next(); // 處理每一行
}
lines.close(); // 關閉 LineIterator
一次性讀取檔案內容(返回每行的文字列表)
//讀取目標檔案每一行資料,返回list
List<String> strs = FileUtils.readLines(new File("D://test/test1"), "utf-8");
讀取檔案內容為位元組陣列
byte[] bytes = FileUtils.readFileToByteArray(new File("D://test/test1"));
讀取檔案內容為字串
用於將檔案內容讀取為字串,可以指定字元編碼。
File fileToRead = new File("readMe.txt");
String fileContent = FileUtils.readFileToString(fileToRead, "UTF-8");
寫入字串文字到檔案
用於將字串寫入檔案,可以指定字元編碼。
File outputFile = new File("output.txt");
String content = "Hello, World!";
FileUtils.writeStringToFile(outputFile, content, "UTF-8");
//將字串寫入檔案,[目標檔案] [寫入的文字內容] [字符集] [是否追加]
//FileUtils.writeStringToFile(new File("D://test/test1"), "file content", "utf-8", true);
//FileUtils.write(new File("D://test/test1"), "target char sequence", "utf-8", true);
//FileUtils.writeByteArrayToFile(new File("D://test/test1"), "bytes".getBytes());//(file,字元陣列)
//FileUtils.writeByteArrayToFile(new File("D://test/test1"), "bytes".getBytes(), true);//(file,字元陣列,是否追加)
//FileUtils.writeByteArrayToFile(new File("D://test/test1"), "bytes".getBytes(), 0, 10);//(file,字元陣列,起始位置,結束位置)
//FileUtils.writeByteArrayToFile(new File("D://test/test1"), "bytes".getBytes(), 0, 10, true);//(file,字元陣列,起始位置,結束位置,是否追加)
將檔案內容附加到已存在的檔案
File fileToAppend = new File("append.txt");
FileUtils.writeStringToFile(fileToAppend, "Appended Text", "UTF-8", true);
用於將文字內容附加到已存在的檔案。
複製輸入流到輸出流
用於將輸入流的內容複製到輸出流,通常用於檔案複製。
InputStream inputStream = ...; // 初始化輸入流
OutputStream outputStream = ...; // 初始化輸出流
IOUtils.copy(inputStream, outputStream);
複製檔案內容到輸出流
用於將檔案內容複製到輸出流,這樣你可以將檔案的內容傳輸到其他地方,如網路連線或壓縮流。
File sourceFile = new File("source.txt");
OutputStream outputStream = ...; // 初始化輸出流
FileUtils.copyFile(sourceFile, outputStream);
複製輸入流到新檔案
FileUtils.copyInputStreamToFile(new FileInputStream("D://test/test1"), new File("D://test/test1"));
複製URL內容到新檔案
FileUtils.copyURLToFile(new URL("file:/test"), new File("D://test/test1"));
關閉輸入流
用於關閉輸入流,忽略任何可能的異常。
InputStream inputStream = ...; // 初始化輸入流 IOUtils.closeQuietly(inputStream);
- 關閉Reader
//用於關閉字元流 Reader,忽略任何可能的異常。
Reader reader = ...; // 初始化 Reader IOUtils.closeQuietly(reader);
關閉輸出流
用於關閉輸出流,忽略任何可能的異常。
OutputStream outputStream = ...; // 初始化輸出流 IOUtils.closeQuietly(outputStream);
- 關閉 Writer
//用於關閉字元流 Writer,忽略任何可能的異常。
Writer writer = ...; // 初始化 Writer
IOUtils.closeQuietly(writer);
獲取檔案的建立時間
File file = new File("file.txt");
BasicFileAttributes attributes = Files.readAttributes(file.toPath(), BasicFileAttributes.class);
FileTime creationTime = attributes.creationTime();
獲取檔案的最後修改時間
File file = new File("file.txt");
long lastModified = file.lastModified(); // 獲取
//file.setLastModified(System.currentTimeMillis()) // 設定
獲取檔案的最後訪問時間
用於獲取檔案的最後訪問時間,以毫秒為單位。
File file = new File("file.txt");
long lastAccessTime = FileUtils.lastAccessed(file);
X 參考文獻
- Apache Commons IO
- https://commons.apache.org/proper/commons-io/
- https://mvnrepository.com/artifact/commons-io/commons-io
- Java工具庫——Commons IO的50個常用方法 - 部落格園
- FileUtils常用方法 - commons-io常用工具類 - 部落格園