Apache Commons之IO使用
1 概述
Commons IO是針對開發IO流功能的工具類庫。
主要包括六個區域:
-
工具類——使用靜態方法執行共同任務
-
輸入——用于InputStream和Reader實現
-
輸出——用于OutputStream和Writer實現
-
過濾器——各種文件過濾器實現
-
比較器——各種文件的java.util.Comparator實現
-
文件監聽器——監聽文件系統事件的組件
2 用戶指南
Commons IO包含工具類、endian classes, line iterator, file filters, file comparators and stream implementations.
更多詳細描述見javadocs。
2.1 工具類
2.1.1 IOUtils
IOUtils包含處理讀、寫和復制的工具方法。方法對InputStream、OutputStream、Reader和Writer起作用。
例如,從一個URL讀取字節的任務,并且打印它們:
InputStream in = new URL( "http://commons.apache.org" ).openStream(); |
使用IOUtils:
InputStream in = new URL( "http://commons.apache.org" ).openStream();
try {
System.out.println(IOUtils.toString(in));
} finally {
IOUtils.closeQuietly(in);
} |
在某些應用領域,這些IO操作是常見的,而這個類可以節省大量的時間。你可以依靠經過良好測試的代碼。
這樣的實用程序代碼,靈活性和速度是最重要的。但是你也應該理解這種方法的局限性。使用上述技術讀取一個1 gb文件將導致試圖創建一個1 gb的字符串對象!
2.1.2 FileUtils
FileUtils類包含使用File對象的工具方法。包括讀寫、復制和比較穩健。
讀取整個文件行:
File file = new File("/commons/io/project.properties");
List lines = FileUtils.readLines(file, "UTF-8"); |
2.1.3 FilenameUtils
FilenameUtils類包含工具方法不需要使用File對象就可以操作文件名。該類致力于屏蔽Unix和Windows之間的不同,避免這些環境之間的轉換(例如,從開發到生產)。
例如,規范文件刪除雙點片段:
String filename = "C:/commons/io/../lang/project.xml"; 返回 |
2.1.4 FileSystemUtils
FileSystemUtils類包含使用JDK不支持的文件系統訪問功能的工具方法。當前,只有獲取驅動的空間大小的方法。注意,這是使用的命令行,而不是本地代碼。
long freeSpace = FileSystemUtils.freeSpace("C:/"); |
2.2 Endian類
不同的計算機體系采用不同的字節排序約定。在所謂的“Little Endian”的體系結構中(例如Intel),低位字節存儲在內存中較低地址,后續字節在較高地址。對于“Big EndIan”體系結構,(例如Motorola),情況恰好相反。
在關聯包中有兩個類:
-
EndianUtils類包含交換Java原始和流的Endian-ness的靜態方法。
-
SwappedDataInputStream類是DataInput接口的實現。使用它,我們能從非本地EndIan-ness的文件讀取數據。
更多細節見http://www.cs.umass.edu/~verts/cs32/endian.html。
2.3 行迭代器
org.apache.commons.io.LineIterator類提供靈活的方式使用一個基于行的文件。可以直接,或通過FileUtils或IOUtils的工廠方法創建實例。推薦使用模式:
處理行 } finally {
LineIterator.closeQuietly(iterator); } |
2.4 文件過濾器
org.apache.commons.io.filefilter包定義一個接口(IOFileFilter)包含java.io.FileFilter和java.io.FilenameFilter。此外,包提供一系列隨時可用的IOFileFilter接口實現,包括允許你組合其它過濾器的實現。這些過濾器能用于列出文件。
2.5 文件比較器
org.apache.commons.io.comparator包提供一系列java.io.File的java.util.Comparator實現。這些比較器能用于排序文件列表和數組。
2.6 流
org.apache.commons.io.input和org.apache.commons.io.output包含各種有用的流實現。
-
空輸出流——默默的吸收發給它的所有數據。
-
Tee輸出流——發送輸出數據到兩個流。
-
字節輸出輸出流——更便捷的JDK類版本。
-
計算流——統計傳遞的字節數。
-
代理流——委托恰當的方法代理。
-
可鎖定的Writer——使用文件鎖提供同步的Writer。
3 最佳實踐
該文檔在IO領域出現一系列“最佳實踐”。
3.1 java.io.File
通常,你必須使用文件和文件名。有很多事情可能出錯:
-
一個類可以在Unix上工作但不能在Windows上工作(反之亦然)
-
由于雙重或丟失路徑分隔符的無效路徑
-
UNC文件名(在Windows上)不使用我的本地文件名功能函數
-
等等
這些都是很好的理由不使用文件名作為字符串。使用java.io.File而不是處理上面的很多中情況。因此,我們最好的實踐推薦使用java.io.File而不是文件名字符串避免平臺依賴。
Commons-io 1.1包括一個專注于文件名處理的類——FilenameUtils。這處理許多這些文件名問題,然而,任然推薦,盡可能,使用java.io.File對象。
public static String getExtension(String filename) {
int index = filename.lastIndexOf('.');
if (index == -1) {
return "";
} else {
return filename.substring(index + 1);
}
} |
足夠簡單?對的,但如果傳入一個完整路徑而不是一個文件名會發生什么?請看下面,完全合法的路徑:“C:\Temp\documentation.new\README”。定義在上面的方法返回“new\README”,肯定不是你想要的。
請使用java.io.File而不是字符串。在FileUtils你將看到圍繞java.io.File的功能函數。
不推薦:
String tmpdir = "/var/tmp";
String tmpfile = tmpdir + System.getProperty("file.separator") + "test.tmp"; InputStream in = new java.io.FileInputStream(tmpfile); |
推薦:
File tmpdir = new File("/var/tmp");
File tmpfile = new File(tmpdir, "test.tmp");
InputStream in = new java.io.FileInputStream(tmpfile); |
3.2 緩沖流
IO性能依賴于緩沖策略。通常,讀取大小為512或1024字節的數據包速度很快,因為這些大小匹配使用在硬盤上的文件系統或文件系統緩沖中的數據包大小。但只要你多次只讀取幾個字節,性能肯定下降。
當你讀取或輸出流尤其是處理文件時確保你正確的緩沖流。只是使用BufferedInputStream裝飾你的FileInputStream。
InputStream in = new java.io.FileInputStream(myfile);
try {
in = new java.io.BufferedInputStream(in);
in.read(.....
} finally {
IOUtils.closeQuietly(in); } |
注意,不要緩沖已經緩沖的流。一些組件像XML解析器可以做自己的緩沖,因此不需要裝飾InputStream傳入XML解析器,但減慢你的代碼。如果你使用CopyUtils或IOUtils不需要使用額外的緩沖流