## **一、概念**
Java中對文件的操作是以流的方式進行的。流是Java內存中的一組有序數據序列。Java將數據從源(文件、內存、鍵盤、網絡)讀入到內存中,形成了流,然后將這些流還可以寫到另外的目的地(文件、內存、控制臺、網絡),之所以稱為流,是因為這個數據序列在不同時刻所操作的是源的不同部分。
<br>
<br>
## **二、分類**
流的分類,Java的流分類比較豐富,剛接觸的人看了后會感覺很暈。流分類的方式很多:
1、按照輸入的方向分,輸入流和輸出流,輸入輸出的參照對象是Java程序。
2、按照處理數據的單位不同分,字節流和字符流,字節流讀取的最小單位是一個字節(1byte=8bit),而字符流一次可以讀取一個字符(1char = 2byte = 16bit)。
3、按照功能的不同分,分節點流和處理流,節點流是直接從一個源讀寫數據的流(這個流沒有經過包裝和修飾),處理流是在對節點流封裝的基礎上的一種流,FileInputStream是一個接點流,可以直接從文件讀取數據,但是BufferedInputStream可以包裝FileInputStream,使得其有緩沖功能。
其實除了以上三種分類外,還有一些常常聽到的一些分類比如:對象流、緩沖流、壓縮流、文件流等等。其實都是節點流和處理流的子分類。當然你也可以創建新的流類型,只要你需要。
<br>
<br>
## **三、流分類的關系**
不管流的分類是多么的豐富和復雜,其根源來自于四個基本的類。這個四個類的關系如下:
:-: 
<br>
<br>
## **四、字節流和字符流的相互轉換**
1、從字節流到字符流:InputStreamReader、OutputStreamWriter類可以實現。
2、從字符流到字節流:可以從字符流中獲取char\[\]數組,轉換為String,然后調用String的API函數getBytes() 獲取到byte\[\],然后就可以通過ByteArrayInputStream、ByteArrayOutputStream來實現到字節流的轉換。
<br>
<br>
## **五.輸入輸出流**
在Java中,把不同類型的輸入輸出源抽象為流,其中輸入和輸出的數據稱為數據流(Data Stream)。數據流是Java程序發送和接收數據的一個通道,數據流中包括輸入流(Input Stream)和輸出流(Output Stream)。通常應用程序中使用輸入流讀出數據,輸出流寫入數據。 流式輸入、輸出的特點是數據的獲取和發送均沿數據序列順序進行。相對于程序來說,輸出流是往存儲介質或數據通道寫入數據,而輸入流是從存儲介質或數據通道中讀取數據,一般來說關于流的特性有下面幾點:
* 先進先出,最先寫入輸出流的數據最先被輸入流讀取到。
* 順序存取,可以一個接一個地往流中寫入一串字節,讀出時也將按寫入順序讀取一串字節,不能隨機訪問中間的數據。
* 只讀或只寫,每個流只能是輸入流或輸出流的一種,不能同時具備兩個功能,在一個數據傳輸通道中,如果既要寫入數據,又要讀取數據,則要分別提供兩個流。
<br>
<br>
## **六.緩沖流**
為了提高數據的傳輸效率,引入了緩沖流(Buffered Stream)的概念,即為一個流配備一個緩沖區(Buffer),一個緩沖區就是專門用于傳送數據的一塊內存。
當向一個緩沖流寫入數據時,系統將數據發送到緩沖區,而不是直接發送到外部設備。緩沖區自動記錄數據,當緩沖區滿時,系統將數據全部發送到相應的外部設備。當從一個緩沖流中讀取數據時,系統實際是從緩沖區中讀取數據,當緩沖區為空時,系統就會從相關外部設備自動讀取數據,并讀取盡可能多的數據填滿緩沖區。 使用數據流來處理輸入輸出的目的是使程序的輸入輸出操作獨立于相關設備,由于程序不需關注具體設備實現的細節(具體細節由系統處理),所以對于各種輸入輸出設備,只要針對流做處理即可,不需修改源程序,從而增強了程序的可移植性。
<br>
<br>
## **七,I/O流類概述**
為了方便流的處理,Java語言提供了java.io包,在該包中的每一個類都代表了一種特定的輸入或輸出流。為了使用這些流類,編程時需要引入這個包。Java提供了兩種類型的輸入輸出流:一種是面向字節的流,數據的處理以字節為基本單位;另一種是面向字符的流,用于字符數據的處理。字節流(Byte Stream)每次讀寫8位二進制數,也稱為二進制字節流或位流。字符流一次讀寫16位二進制數,并將其做一個字符而不是二進制位來處理。需要注意的是,為滿足字符的國際化表示,Java語言的字符編碼采用的是16位的Unicode碼,而普通文本文件中采用的是8位ASCⅡ碼。
<br>
<br>
針對一些頻繁的設備交互,Java語言系統預定了3個可以直接使用的流對象,分別是:
* System.in(標準輸入),通常代表鍵盤輸入。
* System.out(標準輸出):通常寫往顯示器。
* System.err(標準錯誤輸出):通常寫往顯示器。
在Java語言中使用字節流和字符流的步驟基本相同,以輸入流為例,首先創建一個與數據源相關的流對象,然后利用流對象的方法從流輸入數據,最后執行close()方法關閉流。
<br>
<br>
## 讀取控制臺輸入
java 的控制臺輸入由 System.in 完成。
為了獲得一個綁定到控制臺的字符流,你可以把 System.in 包裝在一個 BufferedReader 對象中來創建一個字符流。
下面是創建 BufferedReader 的基本語法:
```
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
```
BufferedReader 對象創建后,我們便可以使用 **read()** 方法從控制臺讀取一個字符,或者用 **readLine()** 方法讀取一個字符串。
<br>
<br>
## **從控制臺讀取多字符輸入**
從 BufferedReader 對象讀取一個字符要使用 read() 方法,它的語法如下:
```
int read() throws IOException
```
每次調用 read() 方法,它從輸入流讀取一個字符并把該字符作為整數值返回。 當流結束的時候返回 -1。該方法拋出 IOException。
下面的程序示范了用 read() 方法從控制臺不斷讀取字符直到用戶輸入 "e"。
```
package day03file;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class day01Stringin {
public static void main(String args[]) throws IOException{
char num;
// 使用System.in創建 BuffereadReader
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("輸入字符:退出請輸入e");
// 讀取字符
do {
num = (char) br.read();
System.out.println(num);
}while (num != 'e');
}
}
```
<br>
<br>
## **從控制臺讀取字符串**
從標準輸入讀取一個字符串需要使用 BufferedReader 的 readLine() 方法。
它的一般格式是:
```
String readLine() throws IOException
```
下面的程序讀取和顯示字符行直到你輸入了單詞"end"。
```
package day03file;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class day02Stringin {
public static void main(String args[])throws IOException{
// 使用System.in 創建 BufferdReader
BufferedReader num = new BufferedReader(new InputStreamReader(System.in));
String str;
System.out.println("Enter lines of text.");
System.out.println("Enter end to quit.");
do {
str = num.readLine();
System.out.println(str);
}while(!str.equals("end"));
}
}
```
<br>
<br>
## **讀寫文件**
如前所述,一個流被定義為一個數據序列。輸入流用于從源讀取數據,輸出流用于向目標寫數據。
下圖是一個描述輸入流和輸出流的類層次圖。
:-: 
<br>
<br>
## **FileInputStream**
該流用于從文件讀取數據,它的對象可以用關鍵字 new 來創建。
有多種構造方法可用來創建對象。
可以使用字符串類型的文件名來創建一個輸入流對象來讀取文件:
```
InputStream f = new FileInputStream("src/web.log");
```
也可以使用一個文件對象來創建一個輸入流對象來讀取文件。我們首先得使用 File() 方法來創建一個文件對象:
```
File f = new File("src/web.log"); InputStream out = new FileInputStream(f);
```
創建了InputStream對象,就可以使用下面的方法來讀取流或者進行其他的流操作。
:-: 
<br>
<br>
## **FileOutputStream**
該類用來創建一個文件并向文件中寫數據。
如果該流在打開文件進行輸出前,目標文件不存在,那么該流會創建該文件。
有兩個構造方法可以用來創建 FileOutputStream 對象。
使用字符串類型的文件名來創建一個輸出流對象:
```
OutputStream f = new FileOutputStream("src/web.log")
```
也可以使用一個文件對象來創建一個輸出流來寫文件。我們首先得使用File()方法來創建一個文件對象:
```
File f = new File("src/web.log"); OutputStream f = new FileOutputStream(f);
```
創建OutputStream 對象完成后,就可以使用下面的方法來寫入流或者進行其他的流操作。
創建OutputStream 對象完成后,就可以使用下面的方法來寫入流或者進行其他的流操作。
| **序號** | **方法及描述** |
| --- | --- |
| **public void close() throws IOException{}** | 關閉此文件輸入流并釋放與此流有關的所有系統資源。拋出IOException異常。 |
| **protected void finalize()throws IOException {}** | 這個方法清除與該文件的連接。確保在不再引用文件輸入流時調用其 close 方法。拋出IOException異常。 |
| **public void write(int w)throws IOException{}** | 這個方法把指定的字節寫到輸出流中。 |
| **public void write(byte\[\] w)** | 把指定數組中w.length長度的字節寫到OutputStream中。 |
```
package day03file;
import java.io.FileOutputStream;
import java.io.OutputStream;
public class day03Stringin {
public static void main(String args[]) {
try {
byte bWrite[] = { 11, 21, 3, 40, 5 };
OutputStream os = new FileOutputStream("test.txt");
for (int x = 0; x < bWrite.length; x++) {
os.write(bWrite[x]); // writes the bytes
}
os.close();
InputStream is = new FileInputStream("test.txt");
int size = is.available();
for (int i = 0; i < size; i++) {
System.out.print((char) is.read() + " ");
}
is.close();
} catch (IOException e) {
System.out.print("Exception");
}
}
}
```
上面的程序首先創建文件test.txt,并把給定的數字以二進制形式寫進該文件,同時輸出到控制臺上。
以上代碼由于是二進制寫入,可能存在亂碼,你可以使用以下代碼實例來解決亂碼問題:
```
import java.io.*;
public class fileStreamTest2 {
public static void main(String[] args) throws IOException {
File f = new File("a.txt");
FileOutputStream fop = new FileOutputStream(f);
// 構建FileOutputStream對象,文件不存在會自動新建
OutputStreamWriter writer = new OutputStreamWriter(fop, "UTF-8");
// 構建OutputStreamWriter對象,參數可以指定編碼,默認為操作系統默認編碼,windows上是gbk
writer.append("中文輸入");
// 寫入到緩沖區
writer.append("\r\n");
// 換行
writer.append("English");
// 刷新緩存沖,寫入到文件,如果下面已經沒有寫入的內容了,直接close也會寫入
writer.close();
// 關閉寫入流,同時會把緩沖區內容寫入文件,所以上面的注釋掉
fop.close();
// 關閉輸出流,釋放系統資源
FileInputStream fip = new FileInputStream(f);
// 構建FileInputStream對象
InputStreamReader reader = new InputStreamReader(fip, "UTF-8");
// 構建InputStreamReader對象,編碼與寫入相同
StringBuffer sb = new StringBuffer();
while (reader.ready()) {
sb.append((char) reader.read());
// 轉成char加到StringBuffer對象中
}
System.out.println(sb.toString());
reader.close();
// 關閉讀取流
fip.close();
// 關閉輸入流,釋放系統資源
}
}
```
- Java自動化測試
- 第一章:Java:基礎內容
- 1.1:Java:Hello Word
- 1.2:Java:熱身
- 1.3:Java:注釋
- 1.4:Java:標識符
- 1.5:Java:常量
- 1.6:Java:基本數據類型
- 1.7:Java:引用類型
- 1.8:Java:String類
- 第二章:Java:運算符
- 2.1:Java:算數運算符
- 2.2:Java:關系運算符
- 2.3:Java:邏輯運算
- 2.4:Java:賦值運算符
- 2.5;Java:三元運算符
- 2.6:Java:位運算符
- 第三章:Java:循環控制語句
- 3.1:Java:for循環
- 3.2:Java:while循環
- 3.3:Java:switch
- 3.4:Java:if else
- 3.5:Java:練習題
- 第四章:Java:函數與全局/局部變量
- 4.1:Java:局部變量
- 4.2:Java:全局變量
- 第五章:Java:方法
- 5.1:Java:初識方法
- 5.2:Java:方法調用
- 5.3:Java:方法重載
- 5.4:Java:構造方法
- 5.5:Java:方法的注意事項
- 第六章:Java:面向對象
- 6.1:Java:小案例
- 6.2:Java:this 關鍵字
- 6.3:Java:super 關鍵字
- 6.4:Java:static 關鍵字
- 6.5:Java:final關鍵字
- 6.6:Java:instanceof 運算符
- 6.7:Java:面向對象之封裝
- 6.8:Java:面向對象之繼承
- 6.9:Java:面向對象之多態
- 第七章:Java:面向對象高級進階
- 7.1:Java:抽象類
- 7.2:Java:Java中String類
- 7.3:Java:interface接口
- 7.4:Java:ArrayList
- 7.5:Java:HashSet
- 7.6:Java:HashMap
- 7.7:Java:反射(reflection)
- 第八章:Java:日志以及異常捕獲
- 8.1:Java:log4j
- 8.2:Java:異常初識基礎
- 8.3:Java:未被捕獲的異常
- 8.4:Java:try和catch的使用
- 8.5:Java:多重catch語句的使用
- 8.6:Java:throws/throw 關鍵字
- 8.7:Java:finally關鍵字
- 8.8:Java:自定義異常
- 第九章:Java:xml and IO
- 9.1:Java:IO基本概念
- 9.2:java:properties
- 9.3:Java:xml基本介紹
- 9.4:Java:xml操作實例
- 第十章:Java:JDBC編程
- 10.1:Java:JDBC介紹
- 10.2:Java:JDBC查詢
- 10.3:Java:JDBC插入
- 10.4:Java:Batch
- 10.5:Java:JDBC連接池
- 第十一章:Java:TestNG
- 11.1:java:TestNG簡介
- 11.2:Java:TestNG小實例
- 11.3:Java:TestNG.xml文件配置
- 11.4:Java:TestNG基本注解
- 11.5:Java:TestNG注解代碼
- 11.6:Java:TestNG預期異常
- 11.7:Java:TestNG忽略測試
- 11.8:Java:TestNG超時測試
- 11.9:Java:TestNG分組測試