### 1.?Java流的分類
按流向分:
輸入流:?可以從其中讀入一個字節序列的對象稱作輸入流。
輸出流:?可以向其中寫入一個字節序列的對象稱作輸出流。
這些字節序列的來源地和目的地可以是文件,而且通常都是文件,但是也可以是網絡連接,甚至是內存塊。抽象類InputStream和OutputStream構成了輸入和輸出類層結構的基礎。
按數據傳輸單位分:
字節流: 以字節為單位傳輸數據的流
字符流: 以字符為單位傳輸數據的流
按功能分:
節點流: 用于直接操作目標設備的流
過濾流: 是對一個已存在的流的鏈接和封裝,通過對數據進行處理為程序提供功能強大、靈活的讀寫功能。
### 2.讀寫字節(InputStream和OutputStream)
(1)InputStream類有一個抽象方法:
~~~
abstract int read()
~~~
這個方法將讀入一個字節,并返回讀入的字節,或者在遇到輸入源結尾時返回-1。在設計具體的輸入流時,必須覆蓋這個方法以提供適用的功能,例如,在FileInputStream類中,這個方法將從某個文件中讀入一個字節。
InputStream類還有若干個非抽象的方法,它們可以讀入一個字節數組,或者跳過大量的字節。這些方法都要調用抽象的read方法,因此各個子類都只需覆蓋一個方法。
(2)OutputStream類定義了下面的抽象方法:
~~~
abstract void write(int b)
~~~
它可以向某個輸出位置寫出一個字節。
(3)read和write方法在執行時都將阻塞,直至字節確實被讀入或寫出。這就意味著如果流不能被立即訪問(通常因為網絡連接忙),那么當前的線程將被阻塞。這使得在這兩個方法等待指定流變為可用的這段時間內,其他的線程就有機會去執行有用的工作。
當你完成對流的讀寫時,應該通過調用close方法來關閉它,這個調用會釋放掉十分有限的操作系統資源。如果一個應用程序打開了過多的流而沒有關閉,那么系統資源將被耗盡。關閉一個輸出流的同時還會沖刷用于該輸出流的緩沖區:所有被臨時置于緩沖區中,以便用更大的包的形式傳遞的字符在關閉輸出流時都將被送出。如果不關閉文件,那么寫出的字節的最后一個包可能將永遠也得不到傳遞。我們可以使用flush方法認為的沖刷這些輸出。
即使某個流類提供了使用原生的read和write功能的某些具體方法,應用系統的程序員還是很少使用它們,因為大家感興趣的數據可能包含數字,字符串和對象,而不是原生字節。
Java提供了眾多從基本InputStream和OutputStream類導出的類,這些類使我們可以處理那些以常用格式表示的數據,而不只是字節。
### 3.流家族
流家族中的成員按照它們的使用方法進行劃分,形成了處理字節和字符的兩個單獨的層次結構。Java中字符是采用Unicode標準,一個字符是16位,即一個字符使用兩個字節來表示。因此JAVA才引入字符流。
java.io包中包含了流式I/O所需要的所有類。在java.io包中有四個基本類:InputStream、OutputStream及Reader、Writer類,它們分別處理字節流和字符流。
| **輸入/輸出** | **字節流** | **字符流** |
|-----|-----|-----|
| 輸入流 | InputStream | Reader |
| 輸出流 | OutputStream | Writer |
字節方面:InputStream和OutputStream類讀寫單子個字節或字節數組。要想讀寫字符串和數字,就需要功能更強大的子類,例如,DataInputStream和DataOutputStream可以以二進制格式讀寫所有的基本Java類型。
字符方面:對于Unicode文本,可以使用抽象類Reader和Writer的子類。Reader和Writer類的基本方法與InputStream和OutputStream中的方法類似。
### 4.字節流InputStream和OutputStream

4.1 InputStream抽象類
InputStream 為字節輸入流,它本身為一個抽象類,必須依靠其子類實現各種功能,此抽象類是表示字節輸入流的所有類的超類。 繼承自InputStream 的流都是向程序中輸入數據的,且數據單位為字節(8bit);
InputStream是輸入字節數據用的類,所以InputStream類提供了3種重載的read方法。Inputstream類中的常用方法:?
| **常用方法** | **描述** |
|-----|-----|
| public abstract int read( ) | 從輸入流中讀取下一個字節數據。返回字節使用高位補0的int類型值表示(0-255),若返回值為-1說明沒有讀取到任何字節,輸入流達到盡頭。 |
| public int read(byte b[ ]) | 從輸入流中讀取b.length個字節的數據放到字節數組b中。返回值是讀取的字節數。如果字節數組的長度為0,不會讀取任何字節數據,返回0,否則至少嘗試去讀取一個字節的數據。如果沒有獲取到字節數據,表示流到達文件末尾,返回-1。第一個讀取的字節存儲在b[0],以此類推。 |
| public int read(byte b[ ], int off, int len) | 從輸入流中讀取至多len個字節的數據放到字節數組b中。返回值是讀取的實際字節數。如果字節數組的長度為0,不會讀取任何字節數據,返回0,否則至少嘗試去讀取一個字節的數據。如果沒有獲取到字節數據,表示流到達文件末尾,返回-1。第一個讀取的字節存儲在b[off],下一個存儲在b[off+1],以此類推。 |
| public int available( ) | 返回輸入流中可以讀取的字節數。注意:若輸入阻塞,當前線程將被掛起,如果InputStream對象調用這個方法的話,它只會返回0,這個方法必須由繼承InputStream類的子類對象調用才有用。注意:雖然很多InputStream的實現類可以正確的返回輸入流的總字節數,但是并不是全都都可以。所以使用這個方法的返回值去分配字節大小來容納輸入流的所有數據一定不是一個正確的方法。 |
| public long skip(long n) | 忽略輸入流中的n個字節,返回值是實際忽略的字節數, 如果為負數,表示沒有跳過任何字節數據。 |
| public int close( ) | 關閉輸入流,釋放分配給輸入流的系統資源。 |
InputStream子類:

InputStream的作用是用來表示那些那些從不同數據源產生輸入的類。這些數據源包括:
- 字節數組
- String對象
- 文件
- "管道",工作方式與實際管道相似,從一端進入,從一端輸出
- 一個由其他種類的流組成的序列,以便我們可以將它們收集合并到一個流內
每一種數據源都有相應的InputStream子類。另外,FilterInputStream也屬于一種InputStream,為"裝飾器"類提供基類,其中"裝飾器"類可以把屬性或有用的接口與輸入流連接在一起。
| **類** | **功能** |
|-----|-----|
| ByteArrayInputStream | 允許將內存中緩沖區當做InputStream使用 |
| StringBufferInputStream | 將String轉換成InputStream |
| FileInputStream | 用于從文件中讀取信息 |
| PipedInputStream | 產生用于寫入相關PipedOutputStream的數據。實現“管道化”概念。 |
| SequenceInputStream | 將兩個或者多個InputStream對象轉換成單一InputStream |
| FilterInputStream | 抽象類,作為“裝飾器”的接口。其中,“裝飾器”為其他的InputStream類提供有用的功能。 |
4.2 OutputSream抽象類
OutputStream提供了3個write方法來做數據的輸出,這個是和InputStream是相對應的。
| **常用方法** | **描述** |
|-----|-----|
| public abstract void write(int b) | 將指定字節寫入到輸出流中。一般是將參數b的低八位(一個字節)寫入到輸出流中。b的高八位被忽略掉。 |
| public void write(byte[] b) | 從字節數組b中向輸出流中寫入b.length個字節數據。 |
| public void write(byte[] b,int off,int len) | 從字節數組b偏移位置為off的開始位置向輸出流寫入len個字節數據。b[off]是第一個被寫入的字節,b[off+len-1]是最后一個被寫入的字節。如果b為null,會拋出NullPointer異常;如果off或者len是負數,或者off+len比字節數組b的長度大,則會拋出IndexOutOfBoundsException異常。 |
| public void flush() | 清空輸出流,并強制將所有緩沖的輸出字節被寫出。 |
| public void close() | 關閉輸出流,釋放分配給輸出流的系統資源。 |
OutputStream的子類:

該類別的類決定了輸出所要去往的目標:字節數組(但不是String,不過你當然可以使用字節數組自己來創建),文件或管道。
| **類** | **功能** |
|-----|-----|
| ByteArrayOutputStream | 在內存中創建緩沖區,所有送往“流”的數據都要放置在此緩沖區。 |
| FileOutputStream | 用于將信息寫至文件。 |
| PipedOutputStream | 任何寫入其中的信息都會自動作為PipedInputStream的輸出。實現“管道化”概念。 |
| FilterOutputStream | 抽象類,作為“裝飾器”的接口。其中,“裝飾器”為其他的OutputStream類提供有用的功能。 |
### 5.字符流 Reader和Writer
當我們初次看到Reader和Writer類時,可能會以為這是兩個用來代替InputStream和OutputStream的類,但實際上不是。盡管一些原始的“流”類庫不再使用(如果使用它們,則會收到編譯器的警告信息),但是InputStream和OutputStream在以面向字節流形式的IO時仍然可以提供有價值的功能。Reader和Writer則提供了兼容Unicode與面向字符的I/O功能。有時候我們還會把來自"字節"層次結構中的類和來自"字符"層次結構中類結合使用。為了實現這個目標,我們要用到"適配器"(adapter)類:InputStreamReader可以把InputStream轉換為Reader,而OutputStream可以把OutputStream轉換為Writer。
設計Reader和Writer繼承層次結構是為了國際化。老的IO流繼承層次結構只能支持8位字節流,并且不能很好的處理16位的Unicode字符。設計它的目的就是為了在所有的IO操作中都支持Unicode。
Reader的子類:

Writer的子類:

### 6.FileInputStream和FileOutputStream
6.1 FileInputStream
FileInputStream 從文件系統中的某個文件中獲得輸入字節。

(1)構造方法
| **構造方法** | **描述** |
|-----|-----|
| FileInputStream(String name) | 使用由name字符串指定路徑名文件創建FileInputStream對象 |
| FileInputStream(File file) | 使用由file對象指定路徑名的文件創建FileInputStream對象 |
~~~
// FileInputStream(String name)
String path = "D:\\Recommended system.txt";
FileInputStream stream = new FileInputStream(path);
// FileInputStream(File file)
File file = new File(path);
FileInputStream stream2 = new FileInputStream(file);
~~~
(2)說明
- 用于讀取諸如圖像數據之類的原始字節流。(要讀取字符流,請考慮使用 FileReader)
- 包含其他一些輸入流,它將這些流用作其基本數據源,它可以直接傳輸數據或提供一些額外的功能。
- 類本身只是簡單地重寫那些將所有請求傳遞給所包含輸入流的 InputStream 的所有方法。
- 其子類可進一步重寫這些方法中的一些方法,并且還可以提供一些額外的方法和字段。
(3)實例
~~~
package com.qunar.io;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class IOUtil {
public static void main(String[] args) {
try {
String path = "D:\\demo.txt";
FileInputStream stream = new FileInputStream(path);
int num = 100;
byte[] buff = new byte[num];
while((stream.read(buff,0,num)) != -1){
System.out.println("NewLine->"+new String(buff));
}//while
stream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
~~~
運行結果:
<table cellspacing="0" cellpadding="0" style="border-collapse:collapse; border:1px solid rgb(187,187,187); width:1098px"><tbody><tr><td style="border-collapse:collapse; border:1px solid rgb(187,187,187); width:1097px"><br/><div><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">NewLine->My?father?was?a?self-taught?mandolin?player.?He?was?one?of?the?best?string?instrument?players?in?our</span></div><div><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">NewLine->?town.?He?could?not?read?music,?but?if?he?heard?a?tune?a?few?times,?he?could?play?it.?When?he?was?yo</span></div><div><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">NewLine->unger,?he?was?a?member?of?a?small?country?music?band.?They?would?play?at?local?dances?and?on?a</span></div><div><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">NewLine->ccasions?would?play?for?the?local?radio?station.?He?often?told?us?how?he?had?auditioned?and?earned?a</span></div><div><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">NewLine->?position?in?a?band?that?featured?Patsy?Cline?as?their?lead?singer.?He?told?the?family?that?after?he</span></div><div><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">NewLine->?was?hired?he?never?went?back.?Dad?was?a?very?religious?man.?He?stated?that?there?was?a?lot?of?drink</span></div><div><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">NewLine->ing?and?cursing?the?day?of?his?audition?and?he?did?not?want?to?be?around?that?type?of?environment.nk</span></div></td></tr></tbody></table>
6.2 FileOutputStream

(1)構造函數
| **構造函數** | **描述** |
|-----|-----|
| FileOutputStream(String name) | 使用由name字符串指定路徑名的文件創建一個新的文件輸出流。 |
| FileOutputStream(String name,boolean append) | 使用由name字符串指定路徑名的文件創建一個新的文件輸出流。如果append參數為true,那么數據將被添加到文件末尾,而具有相同名字的已有文件不會被刪除(末尾添加數據);否則這個方法刪除所有具有相同名字的已有文件。 |
| FileOutputStream(File file) | 使用由file對象指定路徑名的文件創建一個新的文件輸出流。 |
| FileOutputStream(File file,boolean append) | 使用由file對象指定路徑名的文件創建一個新的文件輸出流。如果append參數為true,那么數據將被添加到文件末尾,而具有相同名字的已有文件不會被刪除(末尾添加數據);否則這個方法刪除所有具有相同名字的已有文件。 |
(2)案例
~~~
package com.qunar.io;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class IOUtil {
public static void main(String[] args) {
try {
String path = "D:\\from.txt";
String path2 = "D:\\to.txt";
FileInputStream inputStream = new FileInputStream(path);
FileOutputStream outputStream = new FileOutputStream(path2);
int num = 100;
byte[] buff = new byte[num];
// 由文件寫至內存
while((inputStream.read(buff,0,num)) != -1){
// 由內存寫至文件中
outputStream.write(buff);
}//while
inputStream.close();
outputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
~~~
### 7.DataInputStream和DataOutputStream
DataInputStream和DataOutputStream是對流的擴展,讓我們操作Java基本數據類型更加簡單。
數據輸入流允許應用程序以與機器無關方式從底層輸入流中讀取基本Java數據類型。
~~~
package com.qunar.io;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class IOUtil {
public static void main(String[] args) {
try {
String path = "D:\\to.txt";
// 向文件寫入操作
FileOutputStream outputStream = new FileOutputStream(path);
DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
// 向文件中寫入一個Int值
dataOutputStream.writeInt(10);
// 向文件中寫入一個Double值
dataOutputStream.writeDouble(0.98);
// 向文件中寫入一個Long值
dataOutputStream.writeLong(12l);
// 向文件中寫入一個UTF-8編碼值
dataOutputStream.writeUTF("我來自西安電子科技大學");
//從文件讀取操作
FileInputStream inputStream = new FileInputStream(path);
DataInputStream dataInputStream = new DataInputStream(inputStream);
// 從文件中讀取一個Int值
System.out.println("從文件中讀取一個Int值:" + dataInputStream.readInt());
// 從文件中讀取一個Double值
System.out.println("從文件中讀取一個Double值:" + dataInputStream.readDouble());
// 從文件中讀取一個Long值
System.out.println("從文件中讀取一個Long值:" + dataInputStream.readLong());
// 從文件中讀取一個UTF-8編碼值
System.out.println("從文件中讀取一個UTF-8編碼值:" + dataInputStream.readUTF());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
~~~
運行結果:
<table cellspacing="0" cellpadding="0" style="border-collapse:collapse; border:1px solid rgb(187,187,187); width:1098px"><tbody><tr><td style="border-collapse:collapse; border:1px solid rgb(187,187,187); width:1097px"><br/><div><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">? ?從文件中讀取一個Int值:10</span></div><div><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">? ?從文件中讀取一個Double值:0.98</span></div><div><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">? ?從文件中讀取一個Long值:12</span></div><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">? ?從文件中讀取一個UTF-8編碼值:我來自西安電子科技大學</span>??</td></tr></tbody></table>
本人菜鳥,大牛勿噴,有問題,歡迎留言。。。。
- 前言
- [Hibernate開發之路](1)Hibernate配置
- [Hibernate開發之路](2)Hibernate問題
- [Hibernate開發之路](3)基礎配置
- [Hibernate開發之路](4)ID生成策略
- [Hibernate開發之路](5)聯合主鍵
- [設計模式實踐之路](1)單例模式
- [Java]UDP通信的簡單例子
- [Java]套接字地址InetAddress講解
- [Java開發之路](1)final關鍵字
- [Java開發之路](2)Java字符串
- [Java開發之路](3)Java常用類
- [Java開發之路](4)String、StringBuffer與StringBuilder詳解
- [Java開發之路](5)異常詳解
- [Java開發之路](6)File類的使用
- [Java開發之路](7)RandomAccessFile類詳解
- [Java開發之路](8)輸入流和輸出流
- [Java開發之路](9)對象序列化與反序列化
- [Java開發之路](10)DOM解析XML文檔
- [Java開發之路](11)SAX解析XML文檔
- [Java開發之路](12)JDOM和DOM4J解析XML文檔
- [Java開發之路](14)反射機制
- [Java開發之路](15)注解
- [Java開發之路](16)學習log4j日志
- [Java開發之路](18)關于Class.getResource和ClassLoader.getResource的路徑問題
- [Java開發之路](19)Long緩存問題
- [Java開發之路](20)try-with-resource 異常聲明
- [Java開發之路](21)Comparator與Comparable
- [Java]Java工程師成神之路
- [細說Java](1)圖說字符串的不變性
- [細說Java](2)Java中字符串為什么是不可變的
- [細說Java](3)創建字符串是使用&quot; &quot;還是構造函數?