Java IO流學習總結一:輸入輸出流 轉載請標明出處:http://blog.csdn.net/zhaoyanjun6/article/details/54292148 本文出自 "【趙彥軍的博客】" Java流類圖結構: 流的概念和作用 流是一組有順序的,有起點和終點的位元組集合,是對數據傳輸的總 ...
Java IO流學習總結一:輸入輸出流
轉載請標明出處:http://blog.csdn.net/zhaoyanjun6/article/details/54292148
本文出自【趙彥軍的博客】
Java流類圖結構:
流的概念和作用
流是一組有順序的,有起點和終點的位元組集合,是對數據傳輸的總稱或抽象。即數據在兩設備間的傳輸稱為流,流的本質是數據傳輸,根據數據傳輸特性將流抽象為各種類,方便更直觀的進行數據操作。
IO流的分類
- 根據處理數據類型的不同分為:字元流和位元組流
- 根據數據流向不同分為:輸入流和輸出流
字元流和位元組流
字元流的由來: 因為數據編碼的不同,而有了對字元進行高效操作的流對象。本質其實就是基於位元組流讀取時,去查了指定的碼表。 位元組流和字元流的區別:
- 讀寫單位不同:位元組流以位元組(8bit)為單位,字元流以字元為單位,根據碼表映射字元,一次可能讀多個位元組。
處理對象不同:位元組流能處理所有類型的數據(如圖片、avi等),而字元流只能處理字元類型的數據。
- 位元組流:一次讀入或讀出是8位二進位。
字元流:一次讀入或讀出是16位二進位。
設備上的數據無論是圖片或者視頻,文字,它們都以二進位存儲的。二進位的最終都是以一個8位為數據單元進行體現,所以電腦中的最小數據單元就是位元組。意味著,位元組流可以處理設備上的所有數據,所以位元組流一樣可以處理字元數據。
結論:只要是處理純文本數據,就優先考慮使用字元流。 除此之外都使用位元組流。
輸入流和輸出流
輸入流只能進行讀操作,輸出流只能進行寫操作,程式中需要根據待傳輸數據的不同特性而使用不同的流。
輸入位元組流 InputStream
InputStream
是所有的輸入位元組流的父類,它是一個抽象類。ByteArrayInputStream
、StringBufferInputStream
、FileInputStream
是三種基本的介質流,它們分別從Byte 數組
、StringBuffer
、和本地文件
中讀取數據。PipedInputStream
是從與其它線程共用的管道中讀取數據,與Piped 相關的知識後續單獨介紹。ObjectInputStream
和所有FilterInputStream
的子類都是裝飾流(裝飾器模式的主角)。
輸出位元組流 OutputStream
OutputStream
是所有的輸出位元組流的父類,它是一個抽象類。ByteArrayOutputStream
、FileOutputStream
是兩種基本的介質流,它們分別向Byte 數組
、和本地文件
中寫入數據。PipedOutputStream
是向與其它線程共用的管道中寫入數據。ObjectOutputStream
和所有FilterOutputStream
的子類都是裝飾流。
總結:
- 輸入流:InputStream或者Reader:從文件中讀到程式中;
- 輸出流:OutputStream或者Writer:從程式中輸出到文件中;
節點流
節點流:直接與數據源相連,讀入或讀出。
直接使用節點流,讀寫不方便,為了更快的讀寫文件,才有了處理流。
常用的節點流
- 父 類 :
InputStream
、OutputStream
、Reader
、Writer
- 文 件 :
FileInputStream
、FileOutputStrean
、FileReader
、FileWriter
文件進行處理的節點流 - 數 組 :
ByteArrayInputStream
、ByteArrayOutputStream
、CharArrayReader
、CharArrayWriter
對數組進行處理的節點流(對應的不再是文件,而是記憶體中的一個數組) - 字元串 :
StringReader
、StringWriter
對字元串進行處理的節點流 - 管 道 :
PipedInputStream
、PipedOutputStream
、PipedReader
、PipedWriter
對管道進行處理的節點流
處理流
處理流和節點流一塊使用,在節點流的基礎上,再套接一層,套接在節點流上的就是處理流。如BufferedReader
.處理流的構造方法總是要帶一個其他的流對象做參數。一個流對象經過其他流的多次包裝,稱為流的鏈接。
常用的處理流
- 緩衝流:
BufferedInputStrean
、BufferedOutputStream
、BufferedReader
、BufferedWriter
增加緩衝功能,避免頻繁讀寫硬碟。 - 轉換流:
InputStreamReader
、OutputStreamReader
實現位元組流和字元流之間的轉換。 - 數據流:
DataInputStream
、DataOutputStream
等-提供將基礎數據類型寫入到文件中,或者讀取出來。
轉換流
InputStreamReader
、OutputStreamWriter
要InputStream
或OutputStream
作為參數,實現從位元組流到字元流的轉換。
構造函數
InputStreamReader(InputStream); //通過構造函數初始化,使用的是本系統預設的編碼表GBK。
InputStreamWriter(InputStream,String charSet); //通過該構造函數初始化,可以指定編碼表。
OutputStreamWriter(OutputStream); //通過該構造函數初始化,使用的是本系統預設的編碼表GBK。
OutputStreamwriter(OutputStream,String charSet); //通過該構造函數初始化,可以指定編碼表。
實戰演練
- FileInputStream類的使用:讀取文件內容
package com.app;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class A1 {
public static void main(String[] args) {
A1 a1 = new A1();
//電腦d盤中的abc.txt 文檔
String filePath = "D:/abc.txt" ;
String reslut = a1.readFile( filePath ) ;
System.out.println( reslut );
}
/**
* 讀取指定文件的內容
* @param filePath : 文件的路徑
* @return 返回的結果
*/
public String readFile( String filePath ){
FileInputStream fis=null;
String result = "" ;
try {
// 根據path路徑實例化一個輸入流的對象
fis = new FileInputStream( filePath );
//2. 返回這個輸入流中可以被讀的剩下的bytes位元組的估計值;
int size = fis.available() ;
//3. 根據輸入流中的位元組數創建byte數組;
byte[] array = new byte[size];
//4.把數據讀取到數組中;
fis.read( array ) ;
//5.根據獲取到的Byte數組新建一個字元串,然後輸出;
result = new String(array);
} catch (FileNotFoundException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}finally{
if ( fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return result ;
}
}
- FileOutputStream 類的使用:將內容寫入文件
package com.app;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class A2 {
public static void main(String[] args) {
A2 a2 = new A2();
//電腦d盤中的abc.txt 文檔
String filePath = "D:/abc.txt" ;
//要寫入的內容
String content = "今天是2017/1/9,天氣很好" ;
a2.writeFile( filePath , content ) ;
}
/**
* 根據文件路徑創建輸出流
* @param filePath : 文件的路徑
* @param content : 需要寫入的內容
*/
public void writeFile( String filePath , String content ){
FileOutputStream fos = null ;
try {
//1、根據文件路徑創建輸出流
fos = new FileOutputStream( filePath );
//2、把string轉換為byte數組;
byte[] array = content.getBytes() ;
//3、把byte數組輸出;
fos.write( array );
} catch (FileNotFoundException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}finally{
if ( fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
註意:
- 在實際的項目中,所有的IO操作都應該放到子線程中操作,避免堵住主線程。
FileInputStream
在讀取文件內容的時候,我們傳入文件的路徑("D:/abc.txt"
), 如果這個路徑下的文件不存在,那麼在執行readFile()
方法時會報FileNotFoundException
異常。FileOutputStream
在寫入文件的時候,我們傳入文件的路徑("D:/abc.txt"
), 如果這個路徑下的文件不存在,那麼在執行writeFile()
方法時, 會預設給我們創建一個新的文件。還有重要的一點,不會報異常。
效果圖:
- 綜合練習,實現複製文件,從D盤複製到E盤
package com.app;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class A3 {
public static void main(String[] args) {
A3 a2 = new A3();
//電腦d盤中的cat.png 圖片的路徑
String filePath1 = "D:/cat.png" ;
//電腦e盤中的cat.png 圖片的路徑
String filePath2 = "E:/cat.png" ;
//複製文件
a2.copyFile( filePath1 , filePath2 );
}
/**
* 文件複製
* @param filePath_old : 需要複製文件的路徑
* @param filePath_new : 複製文件存放的路徑
*/
public void copyFile( String filePath_old , String filePath_new){
FileInputStream fis=null ;
FileOutputStream fout = null ;
try {
// 根據path路徑實例化一個輸入流的對象
fis = new FileInputStream( filePath_old );
//2. 返回這個輸入流中可以被讀的剩下的bytes位元組的估計值;
int size = fis.available() ;
//3. 根據輸入流中的位元組數創建byte數組;
byte[] array = new byte[size];
//4.把數據讀取到數組中;
fis.read( array ) ;
//5、根據文件路徑創建輸出流
fout = new FileOutputStream( filePath_new ) ;
//5、把byte數組輸出;
fout.write( array );
} catch (FileNotFoundException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}finally{
if ( fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if ( fout != null ) {
try {
fout.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}