File 類
盡管 java.io
定義的大多數(shù)類用于操作流, 但 File 類卻不是.
File 類沒有指定如何從文件檢索信息以及如何向文件中存儲(chǔ)信息, 但是描述了文件本身的屬性.File 對(duì)象用于獲取和操作與磁盤文件關(guān)聯(lián)的信息, 例如權(quán)限, 時(shí)間, 日期以及目錄路徑, 并且還可以瀏覽子目錄層次.
在許多程序中, 文件是主要的數(shù)據(jù)源和目標(biāo). 盡管在 applet 中, 由于安全原因, 使用文件有一些限制, 但是文件仍然是存儲(chǔ)永久信息以及共享信息的主要資源.
下面的構(gòu)造函數(shù)可以用于創(chuàng)建 file 對(duì)象:
File(String dirPath)
File(String dirPath, String filename)
File(File dirObj, String filename)
File(URI uriObj)
其中, dirPath 是文件的路徑名; filename 是文件或子目錄的名稱; uriObj 是指定目錄的 File 對(duì)象; uriObj 是描述文件的URI對(duì)象.
給出一些例子:
File f1 = new File("/");
File f2 = new File("/", "aaa.bat");
File f3 = new File(f1, "bbb.bat");
注意: Java 使用介于UNIX 和 Windows 約定之間的路徑分隔符. 如果在Windows 版本的java中使用正斜杠
(/)
, 那么路徑仍然會(huì)被正確解析.
請(qǐng)記住, 如果使用 Windows 約定的反斜杠(\)
, 那么在字符串中需要使用轉(zhuǎn)義序列(\\)
.
File 類定義了獲取 File 對(duì)象中標(biāo)準(zhǔn)屬性的方法. 例如, getName()
方法返回文件的名稱; getParent()
方法返回父目錄名; 并且如果文件存在, exists()
方法將返回true, 否則返回false.
大家可以點(diǎn)擊此鏈接來(lái)查看API
流類
InputStream 和 OutputStream 針對(duì)字節(jié)流而設(shè)計(jì), Reader 和 Writer 針對(duì)字符流而設(shè)計(jì). 字節(jié)流類 和 字符流類形成了不同的層次.
通常, 當(dāng)操作字符或字符串時(shí), 應(yīng)當(dāng)使用字符流; 當(dāng)操作字節(jié)或其他二進(jìn)制對(duì)象時(shí), 應(yīng)當(dāng)使用字節(jié)流.
字節(jié)流
字節(jié)流類為處理面向字節(jié)的 I/O 提供了豐富的環(huán)境. 字節(jié)流可以用于任意類型的對(duì)象, 包括二進(jìn)制數(shù)據(jù).
1.InputStream類
定義了java的字節(jié)輸入模型, 并且還實(shí)現(xiàn)了 AutoCloseable 和 Closeable 接口. 當(dāng)發(fā)生 I/O 錯(cuò)誤時(shí), 該類中的大部分都會(huì)拋出 IOException 異常.
方 法 | 描 述 |
---|---|
int available() | 返回當(dāng)前可讀取的輸入字節(jié)數(shù) |
void close() | 關(guān)閉輸入源. |
void mark(int numBytes) | 在輸入流的當(dāng)前位置放置標(biāo)記, 該標(biāo)記在讀入 numBytes 個(gè)字節(jié)之前一直都有效 |
boolean markSupported() | 如果調(diào)用流支持 mark() 或 reset() 方法,就返回true |
int read() | 返回代表下一個(gè)可用字節(jié)的整數(shù). 當(dāng)?shù)竭_(dá)文件末尾時(shí), 返回-1 |
int read(byte buffer[]) | 嘗試讀取buffer.length個(gè)字節(jié)到buffer中, 并返回實(shí)際成功讀取的字節(jié)數(shù). 如果到達(dá)文件末尾, 就返回-1 |
int read(byte buffer[], int offset, int numBytes) | 嘗試讀取 numBytes 個(gè)字節(jié)到 buffer中, 從 buffer[offset] 開始保存讀取的字節(jié), 該方法返回成功讀取的字節(jié)數(shù); 如果到達(dá)文件末尾, 就返回-1 |
void reset() | 將輸入指針重置為前面設(shè)置的標(biāo)記 |
long skip(long numBytes) | 忽略(即跳過(guò)) numBytes個(gè)字節(jié)的輸入, 返回實(shí)際忽略的字節(jié)數(shù) |
2.OutpuStream類
定義流字節(jié)輸出的抽象類, 實(shí)現(xiàn)了 AutoCloseable Closeable以及 Flushable接口.
方 法 | 描 述 |
---|---|
void close() | 關(guān)閉輸出流. |
void flush() | 刷新輸出緩沖區(qū) |
void writer(int b) | 向輸出流中寫入單個(gè)字節(jié). |
void writer(byte buffer[]) | 向輸出流中寫入一個(gè)完整的字節(jié)數(shù)組. |
void writer(byte buffer[], int offset, int numBytes) | 將buffer數(shù)組從buffer[offset]開始的numBytes 個(gè)字節(jié)寫入輸出流中. |
3.FileInputStream 類
兩個(gè)常用的構(gòu)造函數(shù)
FileInputStream(String filePath)
FileInputStream(File fileObj)
這兩個(gè)構(gòu)造函數(shù)都會(huì)拋出 FileNotFoundException 異常. 其中, filePath 是文件的完整路徑名, fileObj 是描述文件的File 對(duì)象.
下面的例子創(chuàng)建了兩個(gè) FileInputStream 對(duì)象, 它們使用相同的磁盤文件, 并且分別使用兩個(gè)構(gòu)造函數(shù)創(chuàng)建的:
FileInputStream f0 = new FileInputStream("/abc.bat");
File f = new File("/abc.bat");
FileInputStream f1 = new FileInputStream(f);
盡管第一個(gè)構(gòu)造函數(shù)可能更常用, 但是使用第二個(gè)構(gòu)造函數(shù), 在將文件附加到輸入流之前, 可以使用 File 類的方法對(duì)象進(jìn)行進(jìn)一步的檢查.
當(dāng)創(chuàng)建 FileInputStream 對(duì)象時(shí), 還可以為讀取而打開了.
下面的例子顯式了如何讀取單個(gè)字節(jié), 整個(gè)字節(jié)字節(jié)數(shù)組以及字節(jié)數(shù)組的一部分.
public class FileInputStreamDemo {
public static void main(String[] args) {
int size;
int i;
try(FileInputStream f = new FileInputStream("FileInputStream.java")) {
System.out.println("Total Available Bytes: " + (size = f.available()));//available() 獲取剩余的字節(jié)數(shù)量
int n = size / 40;
for (i = 0; i < n; i++) {
System.out.println((char) f.read()); //返回代表下一個(gè)可用字節(jié)的整數(shù). 當(dāng)?shù)竭_(dá)文件末尾時(shí), 返回-1
}
byte b[] = new byte[n];
StringBuffer sb = new StringBuffer();
while (f.read(b) != -1) {
sb.append(new String(b, "UTF-8"));
}
System.out.println(sb.toString());
b = new byte[n];
sb = new StringBuffer();
while (f.read(b, 0, n) != -1) {
sb.append(new String(b, "UTF-8"));
}
System.out.println(sb.toString());
} catch (IOException e) {
System.out.println("I/O Error: " + e);
}
}
}
4.FileOutputStream 類
創(chuàng)建能夠用于向文件中寫入字節(jié)的OutputStream 對(duì)象。 該類實(shí)現(xiàn)了AutoCloseable, Closeable 以及 Flushable 接口, 它的4個(gè)構(gòu)造函數(shù)如下所示:
FileOutputStream(String filePath)
FileOutputStream(File file)
FileOutputStream(String filePath, boolean append)
FileOutputStream(File fileObj, boolean append)
它們都可能拋出 FileNotFoundException 異常. 其中, filePath 是文件的完整路徑, fileObj是描述文件的File 對(duì)象. 如果 append 為true, 就以追加方式打開文件.
FileOutputStream 對(duì)象的創(chuàng)建不依賴于已經(jīng)存在的文件. 當(dāng)創(chuàng)建對(duì)象時(shí), FileOutputStream 會(huì)在打開文件之前創(chuàng)建文件. 當(dāng)創(chuàng)建 FileOutputStream 對(duì)象時(shí), 如果試圖打開只讀文件, 會(huì)拋出異常.
public class FileOutputStream {
public static void main(String[] args) {
String source = "Now is the time for all good men\n" +
" to come to the aid of their country\n" +
" and pay their due taxes.";
byte buf[] = source.getBytes();
try (java.io.FileOutputStream f0 = new java.io.FileOutputStream("a.txt");
java.io.FileOutputStream f1 = new java.io.FileOutputStream("b.txt");
java.io.FileOutputStream f2 = new java.io.FileOutputStream("c.txt")){
for (int i = 0; i < buf.length; i += 2) f0.write(buf[i]);
f1.write(buf);
f2.write(buf, buf.length - buf.length/4, buf.length/4);
} catch (IOException e) {
System.out.println("An I/O Error Occurred");
}
}
}
緩沖的字節(jié)流
1.BufferedInputStream 類
緩沖 I/O 是很常見的性能優(yōu)化手段. java 的 BufferedInputStream 類允許將任何 InputStream 對(duì)象封裝到緩沖流中以提高性能.
BufferedInputStream 類有兩個(gè)構(gòu)造函數(shù):
BufferedInputStream(InputStream inputStream)
BufferedInputStream(InputStream inputStream, int bufSize)
第一種形式使用默認(rèn)緩沖區(qū)大小(8192字節(jié))創(chuàng)建緩沖流. 在第二種形式中, 緩沖器大小是由 bufSize 傳遞的. 使緩沖區(qū)大小等于內(nèi)存頁(yè)面, 磁盤塊等大小的整數(shù)倍, 可以明顯提高性能. 然而,這依賴于具體實(shí)現(xiàn).
最優(yōu)的緩沖區(qū)大小通常依賴于宿主操作系統(tǒng), 可用的內(nèi)存數(shù)量以及機(jī)器的配置.
為了充分利用緩沖, 不需要這么復(fù)雜. 比較好的緩沖大小大約是 8 192字節(jié), 并且對(duì)于 I/O 系統(tǒng)來(lái)說(shuō)既是附加比較小的緩沖區(qū), 也是一個(gè)好主意.
這樣的話, 低級(jí)的系統(tǒng)就可以對(duì)磁盤或網(wǎng)絡(luò)獲取多塊數(shù)據(jù), 并將結(jié)果存儲(chǔ)在緩沖區(qū)中. 因此, 即使正在從 InputStream 對(duì)象一次讀取一個(gè)字節(jié), 大部分時(shí)間也都是在操作訪問(wèn)速度很快的內(nèi)存.
2.BufferedOutputStream 類
除了增加 flush() 方法之外, BufferedOutputStream 與所有 OutputStream 類似, flush() 方法用于確保將數(shù)據(jù)緩沖區(qū)寫入被緩沖的流中. BufferedOutputStream 是通過(guò)減少系統(tǒng)實(shí)際寫數(shù)據(jù)的次數(shù)來(lái)提高性能的, 因此可能需要調(diào)用 flush() 方法, 從而要求立即寫入緩沖區(qū)的所有數(shù)據(jù).
下面是兩個(gè)構(gòu)造函數(shù):
BufferedOutputStream(OutputStream outputStream)
BufferedOutputStream(OutputStream outputStream, int bufSize)
第一種方式使用默認(rèn)緩沖區(qū)大小創(chuàng)建緩沖流. 第二種方式, 緩沖區(qū)大小是由 bufSize傳遞的.
PrintStream 類
實(shí)現(xiàn)了 Appendable, AutoCloseable, Closeable 以及 Flushable接口.
PrintStream(OutputStream outputStream)
PrintStream(OutputStream outputStream, boolean autoFlushingOn)
PrintStream(OutputStream outputStream, boolean autoFlushingOn, String charSet) throws UnsupportedEncodingException
在此, outpuStream 指定了用于接收輸出的打開的 OutputStream 對(duì)象. autoFlushingOn 參數(shù)控制每次寫入一個(gè)換行符或字節(jié)數(shù)組, 如果調(diào)用 println() 方法時(shí), 是否自定刷新輸出緩沖區(qū). 如果為true, 就自動(dòng)刷新; 如果為false, 就不自動(dòng)刷新. 第一個(gè)構(gòu)造函數(shù)不自動(dòng)刷新緩沖區(qū). 可以通過(guò) charSet 傳遞的名稱來(lái)指定字符編碼.