1. 程式人生 > >java I/O詳解

java I/O詳解

林炳文Evankaka 原創作品。轉載請註明出處 http://blog.csdn .NET /evankaka
及引用部分http://blog.csdn.net/u012410402/article/details/46652035?ticket=ST-8527-JVAjNZmvQU2PQ6fOep0f-passport.csdn.net

  摘要:本文主要講解了Java I/O解讀與使用例項。

 一、I/O基本概念    

          I/O全稱是Input/Output,Java

的I/O就是Java的輸入與輸出操作。與之相關的介面和類都放在java.io包裡面,因而,在進行Java輸入輸出操作時,需要匯入該包。利用Java的I/O大大地擴充套件了系統的輸入與輸出範疇,不僅可以從控制檯輸入輸出,還可以從其他資料儲存形式進行輸入輸出,例如本地檔案、遠端資料庫等。Java的I/O在檔案資料的讀寫、資料的網路傳送與接收等很多場合發揮著重要作用。


       流是一組有順序的,有起點和終點的位元組集合,是對資料傳輸的總稱或抽象。即資料在兩裝置間的傳輸稱為流,流的本質是資料傳輸,根據資料傳輸特性將流抽象為各種類,方便更直觀的進行資料操作。對於檔案內容的操作主要分為兩大類分別是:字元流和位元組流


(1)位元組流有兩個抽象類:InputStream OutputStream其對應子類有FileInputStream和FileOutputStream實現檔案讀寫。而BufferedInputStream和BufferedOutputStream提供緩衝區功能。



(2)字元流有兩個抽象類:Writer Reader其對應子類FileWriter和FileReader可實現檔案的讀寫操作.BufferedWriter和BufferedReader能夠提供緩衝區功能,用以提高效率。




在JDK API 1.6的版本里,java.io包下一共有12個介面,52個類(異常先不考慮),下面我們逐一分析。

InputStream和OutputStream類:

InputStream和OutputStream是這一類的鼻祖,從Java 1.0就開始存在。那個時候希望所有與輸入有關的類都繼承於InputStream,所有與輸出有關的類都繼承於OutputStream。本文主要講InputStream,根據資料來源的型別不同,可以將InputStream分為以下幾類:

InputStream子類           資料來源型別
ByteArrayInputStream     包含一個記憶體緩衝區,位元組從中取出。
FileInputStream          從檔案中獲得位元組。
ObjectInputStream        用來恢復被序列化的物件。
PipedInputStream         管道輸入流,讀取管道內容。多和PipedOutputStream一起用於多執行緒通訊。
SequenceInputStream      是多種輸入流的邏輯串聯,從第一個輸入流讀取,直到最後一個輸入流。
StringBufferInputStream  讀取的位元組由字串提供。
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

上述6種子類直接繼承於InputStream,可將不同型別的資料來源轉為InputStream物件使用。那麼,InputStream又是什麼樣的呢?

我們可以認為InputStream提供了一種統一的對待輸入的方法,可將多種不同型別的資料來源都用統一的讀取方式對待。要說明的是,InputStream是用來操控位元組輸入流的,它所提供的方法也是針對位元組的。在Java 1.6版本中,InputStream提供了以下方法:

 方法                 解釋
 available()         返回此輸入流下一個方法可以讀取的位元組數。
 close()             關閉此輸入流並釋放相應資源。
 mark(int)           在此輸入流中標記當前的位置。
 markSupported()     測試此輸入流是否支援mark和reset方法。
 read()              從此輸入流中讀取下一個位元組(此方法是抽象方法,子類必須實現該方法)。
 read(byte[])        從輸入流中讀取一定數量的位元組,儲存在引數指定的位元組陣列中。
 read(byte[],int,int)從輸入流中指定位置起讀取若干位元組儲存在指定位元組陣列中。
 reset()             將此輸入流定位到最後一次mark的位置。
 skip(long)          跳過和丟棄此輸入流中資料的若干位元組。
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

JAVA常用的節點流:  

  • 文 件 FileInputStream FileOutputStrean FileReader FileWriter 檔案進行處理的節點流。
  • 字串 StringReader StringWriter 對字串進行處理的節點流。
  • 數 組 ByteArrayInputStream ByteArrayOutputStreamCharArrayReader CharArrayWriter 對陣列進行處理的節點流(對應的不再是檔案,而是記憶體中的一個數組)。
  • 管 道 PipedInputStream PipedOutputStream PipedReaderPipedWriter對管道進行處理的節點流。

常用處理流(關閉處理流使用關閉裡面的節點流)

  •   緩衝流:BufferedInputStrean BufferedOutputStream BufferedReader BufferedWriter

     ---增加緩衝功能,避免頻繁讀寫硬碟。

  •   轉換流:InputStreamReader OutputStreamReader實現位元組流和字元流之間的轉換。
  •   資料流 DataInputStream DataOutputStream 等-提供將基礎資料型別寫入到檔案中,或者讀取出來.

流的關閉順序

  1. 一般情況下是:先開啟的後關閉,後開啟的先關閉
  2. 另一種情況:看依賴關係,如果流a依賴流b,應該先關閉流a,再關閉流b。例如,處理流a依賴節點流b,應該先關閉處理流a,再關閉節點流b
  3. 可以只關閉處理流,不用關閉節點流。處理流關閉的時候,會呼叫其處理的節點流的關閉方法。

注意:

  1. 如果將節點流關閉以後再關閉處理流,會丟擲IO異常。
  2. 如果關閉了處理流,在關閉與之相關的節點流,也可能出現IO異常。(hadoop程式設計檔案流操作中遇到了。)

二、I/O流的分類

根據處理資料型別的不同分為:字元流和位元組流
根據資料流向不同分為:輸入流和輸出流
字元流和位元組流
字元流的由來: 因為資料編碼的不同,而有了對字元進行高效操作的流物件。本質其實就是基於位元組流讀取時,去查了指定的碼錶。位元組流和字元流的區別:
(1)讀寫單位不同:位元組流以位元組(8bit)為單位,字元流以字元為單位,根據碼錶對映字元,一次可能讀多個位元組。
(2)處理物件不同:位元組流能處理所有型別的資料(如圖片、avi等),而字元流只能處理字元型別的資料。
(3)位元組流在操作的時候本身是不會用到緩衝區的,是檔案本身的直接操作的;而字元流在操作的時候下後是會用到緩衝區的,是通過緩衝區來操作檔案,我們將在下面驗證這一點。

結論:優先選用位元組流。首先因為硬碟上的所有檔案都是以位元組的形式進行傳輸或者儲存的,包括圖片等內容。但是字元只是在記憶體中才會形成的,所以在開發中,位元組流使用廣泛。
輸入流和輸出流
對輸入流只能進行讀操作,對輸出流只能進行寫操作,程式中需要根據待傳輸資料的不同特性而使用不同的流。

三、位元組流讀寫操作

3.1、按位元組流讀檔案

InputStream 

此抽象類是表示位元組輸入流的所有類的超類。需要定義 InputStream 的子類的應用程式必須始終提供返回下一個輸入位元組的方法。 
int available() 
返回此輸入流方法的下一個呼叫方可以不受阻塞地從此輸入流讀取(或跳過)的位元組數。 
void close() 
關閉此輸入流並釋放與該流關聯的所有系統資源。 
void mark(int readlimit) 
在此輸入流中標記當前的位置。 
boolean markSupported() 
測試此輸入流是否支援 mark 和 reset 方法。 
abstract int read() 
從輸入流讀取下一個資料位元組。 
int read(byte[] b) 
從輸入流中讀取一定數量的位元組並將其儲存在緩衝區陣列 b 中。 
int read(byte[] b, int off, int len) 
將輸入流中最多 len 個數據位元組讀入位元組陣列。 
void reset() 
將此流重新定位到對此輸入流最後呼叫 mark 方法時的位置。 
long skip(long n) 
跳過和放棄此輸入流中的 n 個數據位元組

其類圖如下:


使用例項如下:

[java]  view plain  copy
  1. package com.lin;  
  2.   
  3. import java.io.File;  
  4. import java.io.FileInputStream;  
  5. import java.io.FileNotFoundException;  
  6. import java.io.IOException;  
  7. import java.io.InputStream;  
  8.   
  9. /** 
  10.  * 功能概要:位元組流讀取檔案 
  11.  *  
  12.  * @author linbingwen 
  13.  * @since 2015年9月5日 
  14.  */  
  15. public class Test1 {  
  16.   
  17.     /** 
  18.      * @author linbingwen 
  19.      * @since 2015年9月5日 
  20.      * @param args 
  21.      * @throws IOException 
  22.      */  
  23.     public static void main(String[] args) {  
  24.         String path = "D:" + File.separator + "test1.txt";  
  25.         readFile1(path);  
  26.         readFile2(path);  
  27.   
  28.     }  
  29.       
  30.     /** 
  31.      * 位元組流讀取檔案:單個字元讀取 
  32.      * @author linbingwen 
  33.      * @since  2015年9月5日  
  34.      * @param path 
  35.      */  
  36.     public static void readFile1(String path) {  
  37.         FileInputStream is = null;  
  38.         try {  
  39.             is = new FileInputStream(path);  
  40.             System.out.println("===============================單個字元讀取begin===============================");  
  41.             int ch = 0;  
  42.             while ((ch = is.read()) != -1) {  
  43.                 System.out.print((char) ch);  
  44.             }  
  45.             System.out.println();  
  46.             System.out.println("===============================單個字元讀取end===============================");        
  47.         } catch (IOException e) {  
  48.             e.printStackTrace();  
  49.         } finally {  
  50.             // 關閉輸入流  
  51.             if (is != null) {  
  52.                 try {  
  53.                     is.close();  
  54.                 } catch (IOException e) {  
  55.                     e.printStackTrace();  
  56.                 }  
  57.             }  
  58.         }  
  59.     }  
  60.     /** 
  61.      * 位元組流讀取檔案:陣列迴圈讀取 
  62.      * @author linbingwen 
  63.      * @since  2015年9月5日  
  64.      * @param path 
  65.      */  
  66.     public static void readFile2(String path) {  
  67.         FileInputStream is = null;  
  68.         try {  
  69.             // 建立檔案輸入流物件  
  70.             is = new FileInputStream(path);  
  71.             // 設定讀取的位元組數  
  72.             int n = 512;  
  73.             byte buffer[] = new byte[n];  
  74.             // 讀取輸入流  
  75.             System.out.println("===============================陣列迴圈讀取begin===============================");  
  76.             while ((is.read(buffer, 0, n) != -1) && (n > 0)) {  
  77. 相關推薦

    java I/O

    林炳文Evankaka 原創作品。轉載請註明出處 http://blog.csdn .NET /evankaka 及引用部分http://blog.csdn.net/u012410402/article/details/46652035?ticket=ST-8527-JVAjNZmvQU2P

    Windows異步I/O

    Windows;異步;IO;當我們對文件進行讀寫時,線程本該是阻塞的,即線程在等待讀寫操作的結束,這種方式稱為同步I/O。Windows在系統層為我們提供了一種高效的機制——異步IO。異步IO提供了這樣一種功能:當你讀取文件時,讀取函數會立刻返回,讀取任務轉交給系統底層自動處理,這樣文件的讀取操作就不會阻塞線

    深入理解JAVA I/O系列三:字符流

    buffer 情況 二進制文件 感到 復制代碼 使用範圍 轉換 fileread 方式 字符流為何存在 既然字節流提供了能夠處理任何類型的輸入/輸出操作的功能,那為什麽還要存在字符流呢?容我慢慢道來,字節流不能直接操作Unicode字符,因為一個字符有兩個字節,字節流一次只

    java I/O

    practice bubuko put bre 技術分享 writer 多媒體 buffered args 概況 I/O流主要分為二大類別:字符流和字節流。 字節流(基本流) 1、字節輸入流 類名:FileInputStream 特點:讀(對文件進行讀取操作)

    java I/O和NI/O

    目錄 I/O概述 字元流 位元組流 理解I/O超類結構 FileInputStream詳解  FileOutputStream詳解 File類 新I/O Java NIO: Channels and Buffers Channels &nbs

    Java I/O : Java中的進位制

    作者:李強強 上一篇,泥瓦匠基礎地講了下Java I/O : Bit Operation 位運算。這一講,泥瓦匠帶你走進Java中的進位制詳解。 一、引子 在Java世界裡,99%的工作都是處理這高層。那麼二進位制,位元組碼這些會在哪裡用到呢? 自問自答:在跨平臺的時候,就凸顯神功了。比如說檔

    JAVA I/O輸入輸出流

    以Unicode字元為導向的stream,表示以Unicode字元為單位從stream中讀取或往stream中寫入資訊。 區別: Reader和Writer要解決的,最主要的問題就是國際化。原先的I/O類庫只支援8位的位元組流,因此不可能很好地處理16位的Unicode字元流。Unicode是國際化的字符集(

    面試必備:Java I/O流,掌握這些就可以說精通了?

    @TOC Java IO概述 IO就是輸入/輸出。Java IO類庫基於抽象基礎類InputStream和OutputStream構建了一套I/O體系,主要解決從資料來源讀入資料和將資料寫入到目的地問題。我們把資料來源和目的地可以理解為IO流的兩端。當然,通常情況下,這兩端可能是檔案或者網路連線。 我們用下面

    Java I/O流的總結

    註意 size 標記接口 ble ansi 寫入 就會 另一個 span I/O的類結構圖 I/O的分類 根據處理的數據類型分為:字節流和字符流。 根據數據流向分為:輸入流和輸出流。 流又可分為節點流和處理流。 節點流 直接與數據源相連 處理流 與節點流一

    java.util包(二)——Connection接口

    操作 相同 元素 叠代 cat roo soft true nbsp Connection接口介紹   Connection接口是java集合的root接口,沒有實現類,只有子接口和實現子接口的各種容器。主要用來表示java集合這一大的抽象概念。   Connection接

    java對象

    add splay view created 元素 繼承關系 外部 優化 csdn java對象詳解 內存布局 普通對象布局 數組的內存布局 內部類的內存布局 對象分解 對象頭-mark word(8字節) 實例數據 對齊填充(可選) java鎖分析

    Java泛型

    對象數組 整形 泛型方法 tty 接受 一個 div -m color 泛型的本質是參數化類型,也就是說所操作的數據類型被指定為一個參數。 假定我們有這樣一個需求:寫一個排序方法,能夠對整形數組、字符串數組甚至其他任何類型的數組進行排序,該如何實現? 答案是可以使用 Ja

    Java I/O 操作及優化建議

    java.net 底層 str 面向對象 div 選擇 static 右移 linux Java I/OI/O。即 Input/Output(輸入/輸出) 的簡稱。就 I/O 而言。概念上有 5 種模型:blocking I/O,nonblocking I/O。I/O

    Java常量池

    回收 array 數值 編譯期 二進制格式 new 保持 占用 get 轉自:http://www.cnblogs.com/iyangyuan/p/4631696.html jvm虛擬內存分布圖: 程序計數器:JVM執行程序的流水線。 本地方法棧:JVM調用操作系統方法所

    Java線程(一)

    線程 thread runnable 程序、進程、線程的概念 程序(program):是為完成特定任務、用某種語言編寫的一組指令的集合。即指一段靜態的代碼,靜態對象。 進程(process):是程序的一次執行過程,或是正在運行的一個程序。動態過程:有它自身的產生、存在和消亡的過程。 如

    Java反射機制

    java 反射 反射機制 工廠模式 1反射機制是什麽反射機制是在運行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法;對於任意一個對象,都能夠調用它的任意一個方法和屬性;這種動態獲取的信息以及動態調用對象的方法的功能稱為java語言的反射機制。在面向對象的世界裏,萬事萬物皆對象.在ja

    JAVA環境配置

    指向 微軟 ssp cep 解釋 引入 bin testcase loader 步驟:一下載安裝JDK(註意版本)二配置環境變量 JAVA_HOME:JDK的安裝路徑 CLASSPATH:.;%JAVA_HOME%\lib;%JAVA_HOME%\lib\too

    Java反射機制

    ride length 數組大小 conf array arraycopy 動態調用 ray info Java反射機制詳解 |目錄 1反射機制是什麽 2反射機制能做什麽 3反射機制的相關API ·通過一個對象獲得完整的包名和類名 ·實例化Class類對象 ·獲

    java虛擬機

    image 種類 棧的操作 cms gc float align pool 不定 記錄 註: 此篇文章可以算是讀《深入理解Java虛擬機:JVM高級特性與最佳實踐》一書後的筆記總結加上我個人的心得看法。 整體總結順序沿用了書中順序,但多處章節用自己的話或直白或擴展的進行

    java 常量池

    例如 ava color str blog 註意 如果 .cn 運行 參考資料:http://www.cnblogs.com/holos/p/6603379.html 註意: 1.首先,我們平時在討論字符串新建問題時所說的常量池其實指的是全局字符串常量池。並不是運行時常量池