[Java SE] 基礎工具庫 : Apache Commons IO

千千寰宇發表於2024-07-09

1 總述

  • Commons IOApache Commons IO)是一個廣泛用於 Java 開發的開源工具庫,由Apache軟體基金會維護和支援。這個庫旨在簡化檔案和流操作,提供了各種實用工具類和方法,以便更輕鬆地進行輸入輸出操作。以下是 Commons IO 的一些主要特點和功能:
  1. 檔案操作:Commons IO 提供了大量用於檔案和目錄操作的方法,包括建立、刪除、重新命名、複製、移動檔案,以及遞迴地操作目錄結構。
  2. 流處理:你可以使用 Commons IO 處理各種輸入和輸出流,包括讀取、寫入和操作流資料。這對於處理文字檔案、二進位制檔案以及網路通訊非常有用。
  3. 檔案過濾和篩選:Commons IO 允許你輕鬆地篩選檔案和目錄,根據各種條件,如副檔名、檔案大小、最後修改時間等。
  4. 檔案內容操作:你可以比較兩個檔案的內容,查詢檔案中的文字,以及進行替換等操作。
  5. 自動關閉流:Commons IO 提供了自動關閉流的功能,確保在處理檔案和流時,資源得以正確釋放,而無需顯式呼叫close()方法。
  6. 異常處理:庫中的方法通常會處理 I/O 異常,以簡化程式碼中的錯誤處理。
  7. 效能和可靠性: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
  1. https://commons.apache.org/proper/commons-io/
  2. https://mvnrepository.com/artifact/commons-io/commons-io
  • Java工具庫——Commons IO的50個常用方法 - 部落格園
  • FileUtils常用方法 - commons-io常用工具類 - 部落格園

相關文章