Commons IO 官方文件
Common IO 是一個工具庫,用來幫助開發IO功能 它包括6個主要部分
- Input –
InputStream
和Reader
實現 - Output –
OutputStream
和Writer
實現 - Filters – 多種檔案過濾器實現(定義了
IOFileFilter
介面,同時繼承了FileFilter
和FilenameFilter
介面) - Comparators – 用於檔案比較的多種
java.util.Comparatot
實現
發行版本
- Commons IO 2.5 (requires JDK 1.6+)
- Commons IO 2.4 (requires JDK 1.6+)
- Commons IO 2.2 (requires JDK 1.5+)
使用者指南
Commons-IO 包括 工具類 (utility classes
), 位元組序列類 (endian classes
), 行迭代器 (line iterator
), 檔案過濾器 (file filters
),檔案比較器 (file comparators
) 和 流實現 (stream implementations
).
Utility classes
IOUtils
IOUtils 包含一些工具類,用於處理讀,寫和拷貝,這些方法基於 InputStream
, OutputStream
, Reader
和 Writer
例如,思考一個任務,從URL中讀取byte資料,並列印。通常會這樣做:
InputStream in = new URL( "http://commons.apache.org" ).openStream(); try { InputStreamReader inR = new InputStreamReader( in ); BufferedReader buf = new BufferedReader( inR ); String line; while ( ( line = buf.readLine() ) != null ) { System.out.println( line ); } } finally { in.close(); }
使用 IOUtils
類,可以這樣:
InputStream in = new URL( "http://commons.apache.org" ).openStream();
try {
System.out.println( IOUtils.toString( in ) );
} finally {
IOUtils.closeQuietly(in);
}
在某些應用領域,例如IO操作中是很常見的,這個類可以節省很多時間。並且你可以依賴於經過全面測試的程式碼。
對於這類的程式碼,靈活性和速度是最重要的。然而你也應該明白這麼做的限制。使用以上的方式讀取一個1GB的檔案將會試圖創造一個1GB字串物件
FileUtils
FileUtils 包含一些工具類,它們基於File
物件工作,包括讀,寫,拷貝和比較檔案
例如逐行讀取整個檔案你可以使用:
File file = new File("/commons/io/project.properties");
List lines = FileUtils.readLines(file, "UTF-8");
FilenameUtils
FilenameUtils包含一些工具類,它們基於檔名工作而不是File
物件。這個類旨在 在Unix和Windows環境下保持一致,幫助在兩個環境下過渡(如從開發環境到生成環境)
例如,正常化檔名,刪除..
片段:
String filename = "C:/commons/io/../lang/project.xml";
String normalized = FilenameUtils.normalize(filename);
// result is "C:/commons/lang/project.xml"
FileSystemUtils
FileSystemUtils包含一些工具類,基於檔案系統訪問功能不被JDK支援。目前,只有一個方法就是得到驅動器空餘空間。注意這使用命令列而不是 native code。
例如得到驅動器空餘空間:
long freeSpace = FileSystemUtils.freeSpace("C:/");
Endian classes
不同的計算機架構對應位元組序採用不同的約定,在所謂的”小端”架構(例如Intel),低位位元組被儲存在記憶體的最低位元組,之後的位元組在高地址。對於”大端”架構(如Motoroal),情況相反。
在這個包中有兩個相關聯的類:
- EndianUtils 包含靜態方法來交換Java基本型別和流的位元組序
Line iterator
org.apache.commons.io.LineIterator
類提供類靈活的方式操作基於行的檔案。通過FileUtils
或 IOUtils
中的工廠方法,可以直接建立一個例項。推薦的使用方法是:
LineIterator it = FileUtils.lineIterator(file, "UTF-8");
try {
while (it.hasNext()) {
String line = it.nextLine();
/// do something with line
}
} finally {
LineIterator.closeQuietly(iterator);
}
File filters
org.apache.commons.io.filefilter
包定義了一個介面 (IOFileFilter),同時繼承了 java.io.FileFilter
和 java.io.FilenameFilter
介面。除此之外還提供了一系列可以使用的IOFileFilter
介面實現,包括允許你組合其他過濾器。這些過濾器可以用來遍歷檔案或在FileDialog
中使用。
File comparators
org.apache.commons.io.comparator
包為java.io.File
提供一些java.util.Comparator
實現。這些比較器可以用來排序列表和檔案數字。
Streams
org.apache.commons.io.input
和 org.apache.commons.io.output
包中包含一些有用的流實現。他們包括:
- Null output stream – 默默吸收所有發給它的資料
- Tee output stream – 傳送輸出資料給兩個流而不是一個
- Byte array output stream – 這是一個比JDK更快的版本
- Counting streams – 計算通過的位元組數
- Proxy streams – 在代理中委託正確的方法
- Lockable writer – 使用鎖檔案提供寫入同步
最佳實踐
本文件提供一些在IO領域的最佳實踐
java.io.File
通常,你要處理檔案和檔名。有很多地方可能出錯:
- 一個類在Uinx下正常工作但是在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
代替字串作為檔名。這個類提供的方法經過了良好的測試。在 FileUtil
你會發現其他關於 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);
Buffering streams
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 解析器可能自己緩衝,所以裝飾傳遞給 XML 解析器的InputStream
只會拖慢的程式碼。如果你使用我們的 CopyUtils
或者 IOUitls
你不需要另外緩衝,你使用的程式碼在複製過程的已經緩衝。經常檢查Javadocs中的資訊。另一種情況,當你向ByteArrayOutputStream
中寫入時,緩衝不是必須的,因為你只寫入記憶體。