天天看點

Java IO流學習總結一:輸入輸出流

Java IO流學習總結一:輸入輸出流

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:從程式中輸出到檔案中;

節點流

節點流:直接與資料源相連,讀入或讀出。

直接使用節點流,讀寫不友善,為了更快的讀寫檔案,才有了處理流。

Java IO流學習總結一:輸入輸出流

常用的節點流

  • 父 類 :

    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。
InputStreamReader(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();
				}
			}
		}
	}


}

           

注意:

  1. 在實際的項目中,所有的IO操作都應該放到子線程中操作,避免堵住主線程。
  2. FileInputStream

    在讀取檔案内容的時候,我們傳入檔案的路徑(

    "D:/abc.txt"

    ), 如果這個路徑下的檔案不存在,那麼在執行

    readFile()

    方法時會報

    FileNotFoundException

    異常。
  3. 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();
				}	
			}
		}
	}
}