1. 程式人生 > >JAVA:IO流 之 節點流與處理流(2)

JAVA:IO流 之 節點流與處理流(2)

1. 流的分類

  • 按資料流的方向不同:輸入流,輸出流。
  • 按處理資料單位不同:位元組流,字元流。
    (1) 位元組流:資料流中最小的資料單元是位元組。
    (2)字元流:資料流中最小的資料單元是字元, Java中的字元是Unicode編碼,一個字元佔用兩個位元組。
  • 按功能不同:節點流,處理流。
    (1)程式用於直接操作目標裝置所對應的類叫節點流。
    (2)程式通過一個間接流類去呼叫節點流類,以達到更加靈活方便地讀寫各種型別的資料,這個間接流類就是處理流。

2. 節點流

2.1 節點流的型別

這裡寫圖片描述

  • (1)File 檔案流。對檔案進行讀、寫操作 :FileReader、FileWriter、FileInputStream、FileOutputStream。、
  • (2)Memory
    1)從/向記憶體陣列讀寫資料: CharArrayReader與 CharArrayWriter、ByteArrayInputStream與ByteArrayOutputStream。
    2)從/向記憶體字串讀寫資料 StringReader、StringWriter、StringBufferInputStream。
  • (3)Pipe管道流。 實現管道的輸入和輸出(程序間通訊): PipedReader與PipedWriter、PipedInputStream與PipedOutputStream。

2.2 節點流執行的圖示

這裡寫圖片描述

3. 處理流

3.1 處理流的型別

這裡寫圖片描述
- (1)Buffering緩衝流:在讀入或寫出時,對資料進行快取,以減少I/O的次數:BufferedReader與BufferedWriter、BufferedInputStream與BufferedOutputStream。
- (2)Filtering 濾流:在資料進行讀或寫時進行過濾:FilterReader與FilterWriter、FilterInputStream與FilterOutputStream。
- (3)Converting between Bytes and Characters 轉換流:按照一定的編碼/解碼標準將位元組流轉換為字元流,或進行反向轉換(Stream到Reader):InputStreamReader、OutputStreamWriter。
- (4)Object Serialization 物件流 :ObjectInputStream、ObjectOutputStream。
- (5)DataConversion資料流: 按基本資料型別讀、寫(處理的資料是Java的基本型別(如布林型,位元組,整數和浮點數)):DataInputStream、DataOutputStream 。
- (6)Counting計數流: 在讀入資料時對行記數 :LineNumberReader、LineNumberInputStream。
- (7)Peeking Ahead預讀流: 通過快取機制,進行預讀 :PushbackReader、PushbackInputStream。
- (8)Printing列印流: 包含方便的列印方法 :PrintWriter、PrintStream。

3.2 處理流執行的圖示

這裡寫圖片描述

3.3 緩衝流

  • 【1】對I/O進行緩衝是一種常見的效能優化,緩衝流為I/O流增加了記憶體緩衝區,增加緩衝區的兩個目的:
    (1)允許Java的I/O一次不只操作一個字元,這樣提高䇖整個系統的效能;
    (2)由於有緩衝區,使得在流上執行skip、mark和reset方法都成為可能。

  • 【2】緩衝流:它是要“套接”在相應的節點流之上,對讀寫的資料提供了緩衝的功能,
    提高了讀寫的效率,同時增加了一些新的方法。例如:BufferedReader中的readLine方法,
    BufferedWriter中的newLine方法。

  • 【3】J2SDK提供了4種快取流,常用的構造方法為:

//字元輸入流
BufferedReader(Reader in)//建立一個32位元組的緩衝區
BufferedReader(Reader in, int size)//size為自定義快取區的大小

//字元輸出流
BufferedWriter(Writer out)
BufferedWriter(Writer out, int size)

//位元組輸入流
BufferedInputStream(InputStream in)
BufferedInputStream(InputStream in, int size)

//位元組輸出流
BufferedOutputStream(OutputStream in)
BufferedOutputStream(OutputStream in, int size)
  • 【4】其他
    (1)緩衝輸入流BufferedInputSTream除了支援read和skip方法意外,還支援其父類的mark和reset方法;
    (2)BufferedReader提供了一種新的ReadLine方法用於讀取一行字串(以\r或\n分隔);
    (3)BufferedWriter提供了一種新的newLine方法用於寫入一個行分隔符;
    (4)對於輸出的緩衝流,BufferedWriter和BufferedOutputStream,寫出的資料會先在記憶體中快取,
    使用flush方法將會使記憶體的資料立刻寫出。

  • 示例1:

import java.io.*;
public class TestBufferStream1 {
  public static void main(String[] args) {
    try {
      FileInputStream fis = new FileInputStream(
          "d:\\JavaProject\\demo13\\ProcessingStream\\TestBufferStream1.java");
      BufferedInputStream bis = new BufferedInputStream(fis);
      int c = 0;
      System.out.println((char)bis.read());
      System.out.println((char)bis.read());
      bis.mark(100);/*在當前輸入流的當前位置上做一個標誌,允許最多再讀入100個位元組*/
      for(int i=0;i<=10 && (c=bis.read())!=-1;i++){
        System.out.print((char)c+" ");
      }
      System.out.println(); 
      bis.reset();/*把輸入指標返回到以前所做的標誌處*/
      for(int i=0;i<=10 && (c=bis.read())!=-1;i++){
        System.out.print((char)c+" ");
      }
      bis.close();
    } catch (IOException e) {e.printStackTrace();}
  }
}
  • 示例2:
import java.io.*;
public class TestBufferStream2
{
    public static void main(String[] args)
    {
    try{
    BufferedWriter bw = new BufferedWriter(new FileWriter("D:\\JavaProject\\demo13\\BufferStream\\dat2.txt"));
    BufferedReader br = new BufferedReader(new FileReader("D:\\JavaProject\\demo13\\BufferStream\\dat2.txt"));
    String s = null;
    for(int i=0;i<10;i++)
    {
        s = String.valueOf(Math.random());//產生一個小於1的正的隨機數,並轉換成字串形式
        bw.write(s);//把字串s寫入到dat2.txt檔案中
        bw.newLine();//寫入一個行分隔符
    }
    bw.flush();//使用flush方法將會使記憶體的資料立刻寫出

    while((s=br.readLine()) != null)
    {
        System.out.println(s);
    }
    bw.close();
    br.close();
    }
    catch(IOException e)
    {
        e.printStackTrace();
    }

    }
}

3.4 轉換流

  • 轉換流有兩種:
    (1)InputStreamReader:將位元組流轉換為字元流;
    (2)OutputStreamWriter:將字元流轉換為位元組流。
  • 什麼時候使用轉換流?由以下分析: 流物件很多,就要明確使用哪個流物件。
通過三點來完成: 
    1、明確資料的來源和資料到達的目的地。
                 來源:輸入流 [InputStream,Reader]。 
                 目的:輸出流 [OutputStream,Writer]。 
    2、操作的資料是否是純文字。  
                 是:字元流,使用Reader與Writer; 
                 否:位元組流,使用InputStreamOutputStream3、明確要使用哪個具體的物件。 通過裝置來進行區分: 
                 源裝置:記憶體用陣列,硬碟就加file,鍵盤用System.in; 
                 目的裝置:記憶體用陣列,硬碟就加file,鍵盤用System.out。 
    4、明確是否還需要其他額外功能:例如 
                (1)是否需要較高的效率,即是否需要使用緩衝區,是就加上Buffered;
                (2)是否需要轉換,是,就使用轉換流,InputStreamReader 和 OutputStreamWriter。
  • 用一個例子簡單的說明: 將鍵盤錄入的資料儲存到一個檔案中,輸入“over”時表示錄入結束。 詳細分析:
源:從InputStream,Reader中選擇; 因為是鍵盤錄入的是純文字,所以使用Reader。 
裝置:鍵盤,所以用System.in; 發現System.in是位元組流的操作,與Reader(字元流)矛盾,
這時就要用到轉換流 InputStreamReader 。為了提高操作效率,使用緩衝技術,選擇BufferedReader。 

目的:從 OutputStream,Writer中選擇。 因為是文字檔案,所以選擇Writer。 
裝置:硬碟上,一個檔案,選擇FileWriter。 為了提高操作效率,使用緩衝技術,選擇BufferedWriter。 
  • 示例1:
import java.io.*; 
    class ReadinFile 
        { 
            public static void main(String[] args)throws IOException //這裡為了方便閱讀,先不做異常處理。 
            { 
                BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in)); 
                BufferedWriter bufw=new BufferedWriter(new FileWriter("readin.txt")); 
                String line=null; 
                while((line=bufr.readLine())!=null) 
                { 
                    if("over".equals(line)) break; 
                    bufw.write(line); 
                    bufw.newLine(); 
                } 
                bufw.close(); 
                bufr.close(); 
            } 
        }
  • 示例2:
import java.io.*;
public class TestTransForm 
{
    public static void main(String[] args) throws IOException //這裡為了方便閱讀,先不做異常處理。 
    {
        InputStreamReader isr = new InputStreamReader(System.in);
        BufferedReader br = new BufferedReader(isr);
        OutputStreamWriter osw = new OutputStreamWriter(
                                 new FileOutputStream("D:\\JavaProject\\demo13\\TransStream\\TransForm.txt",true));
        BufferedWriter bw = new BufferedWriter(osw);
        String str = null;
        str = br.readLine();
        while(str != null)
        {
            if(str.equalsIgnoreCase("exit")) break;
            bw.write(str);
            bw.newLine();
            str = br.readLine();
        }
        br.close();
        bw.close();
    }
}
  • 注意:
    (1)構造方法:public FileOutputStream(String name,boolean append) throws FileNotFoundException
    如果append為True,輸出位元組流就寫入檔案的末尾,而不是開頭(覆蓋原來的內容);
    如果append為False,輸出位元組流就寫入檔案的開頭,即覆蓋原來的內容從檔案開始處寫內容。
    (2)構造方法:public FileOutputStream(String name) throws FileNotFoundException
    每次覆蓋原檔案的內容,從檔案開始處寫內容。

3.5 資料流——資料的儲存和資料恢復

  • 資料流:DataInputStream和DataOutputStream
    (0)DataInputStream和DataOutputStream是面向位元組的,因此要使用InputStream和OutputStream。
    (1)DataInputStream和DataOutputStream分別繼承InputStream和OutputStream,
    它們屬於處理流,需要分別“套接”在InputStream和OutputStream型別的節點流上。
    (2)DataInputStream和DataOutputStream提供了可以存取與機器無關的Java原始類資料(如:int,double等)的方法。
    (3)DataInputStream和DataOutputStream的構造方法:
     DataInputStream(InputStream in)
     DataOutputStream(OutputStream out
  • 示例1:
import java.io.*;
public class TestDataStream
{
    public static void main(String[] args) throws IOException
    {
        FileOutputStream fout = new FileOutputStream("D:/JavaProject/demo13_IO/DataStream/demo.txt",true);
        BufferedOutputStream bout = new BufferedOutputStream(fout);
        DataOutputStream dout = new DataOutputStream(bout);
        /*DataOutputStream,BufferedOutputStream,FileOutputStream這裡使用了流棧。*/

        dout.writeInt(110);
        dout.writeUTF("hello,中國");
        dout.writeFloat(3.14f);
        dout.writeChar(97);/*97對應的是'a'*/
        dout.close();/*如果正在使用一個流棧,程式關閉最上面的一個流也就自動的關閉了棧中的所有底層流。*/

        FileInputStream fin = new FileInputStream("D:/JavaProject/demo13_IO/DataStream/demo.txt");
        BufferedInputStream bin = new BufferedInputStream(fin);
        DataInputStream din = new DataInputStream(bin);

        int i = din.readInt();
        String str = din.readUTF();
        float f = din.readFloat();
        char c = din.readChar();
        fin.close();/*如果正在使用一個流棧,程式關閉最上面的一個流也就自動的關閉了棧中的所有底層流。*/
        System.out.println("int:"+i+"\nString:"+str+"\nfloat:"+f+"\nchar:"+c);
    }

}
  • 編譯,執行:
D:\JavaProject\demo13_IO\DataStream>javac TestDataStream.java

D:\JavaProject\demo13_IO\DataStream>java TestDataStream
int:110
String:hello,中國
float:3.14
char:a
  • 注意:
        int i = din.readInt();
        String str = din.readUTF();
        float f = din.readFloat();
        char c = din.readChar();
        /*此段程式碼的順序不能亂,要保證先寫入的先讀出來的原則,否則會出現錯誤。
        *    因此,我們在寫程式碼的時候,我們必須:
        *         要麼為檔案中的資料採用固定的格式;
        *         要麼將額外的資訊儲存到檔案中,以便能夠對其進行解析以確定資料的尋訪位置。
        */

相關推薦

FPGA同步復位非同步復位2

為了避免純粹的同步復位和純粹非同步復位的問題,可以使用一種叫做同步化的非同步復位,我們稱其為第三類復位。這種復位完全結合了非同步復位和同步復位的優勢,我們知道非同步復位的優勢是不參與資料路徑,所以不影響資料路徑速度,而復位幾乎是瞬間起作用;而同步復位的優勢是百分百地同步時

Python學習基本數據類型變量基礎條件及循環

sets 但是 while循環 spl view put 算數運算 sse 邏輯運算 一.數據類型和變量 1.可變與不可變數據類型   可變數據類型:在id不變的情況下,數據類型內部的元素可以改變   列表   字典   不可變數據類型:value改變,id也跟著改變

Java常用的八種排序演算法程式碼實現桶排序、計數排序、基數排序

三種線性排序演算法:桶排序、計數排序、基數排序 線性排序演算法(Linear Sort):這些排序演算法的時間複雜度是線性的O(n),是非比較的排序演算法 桶排序(Bucket Sort)   將要排序的資料分到幾個有序的桶裡,每個桶裡的資料再單獨進行排序,桶內排完序之後,再把桶裡的

Java常用的八種排序演算法程式碼實現歸併排序法、快速排序法

注:這裡給出的程式碼方案都是通過遞迴完成的 --- 歸併排序(Merge Sort):   分而治之,遞迴實現   如果需要排序一個數組,我們先把陣列從中間分成前後兩部分,然後對前後兩部分進行分別排序,再將排好序的數組合並在一起,這樣整個陣列就有序了   歸併排序是穩定的排序演算法,時間

微服務架構父專案及服務註冊發現中心Eureka搭建

1、建立spring boot父專案 (1.1)file---new----project: (1.2)選擇spring initializr,選擇自己本地安裝的jdk。點選next (1.3)填寫自己的專案資訊,next: (1.4)選擇core-devtools

Java常用的八種排序演算法程式碼實現氣泡排序法、插入排序法、選擇排序法

這三種排序演算法適合小規模資料排序 ---   共同點:基於比較,時間複雜度均為O(n2),空間複雜度均為O(1)(原地排序演算法)   不同點:插入排序和氣泡排序是穩定的排序演算法,選擇排序不是 ---   穩定排序演算法:可以保持數值相等的兩個物件,在排序之

從零開始學C++虛擬函式多型虛擬函式表指標、虛解構函式、object slicing虛擬函式、C++物件模型圖

#include <iostream>using namespace std;class CObject {public:     virtual void Serialize()     {         cout << "CObject::Serialize ..." <&

在STM32上實現NTFS5GPT分區表的C語言實現2GPT實現以及統一方式讀取磁盤分區

tfs 下載 數據 特殊 dpt 屬性列表 handle 系統分區 成了   上一節實現了主GPT頭的信息提取,這一節繼續提取整個的GPT數據,並且將GPT分區表和MBR分區表兩種格式融合成一個模塊,使主調函數(也可以說是使用者)不需要關心磁盤的分區表類型:它太底層了,確實

C有符號無符號

C語言 有符號數 無符號數 我們在 C 語言中經常會見到 unsigned 關鍵字,那麽這是什麽意思呢?在計算機內,數據類型分為有符號和無符號兩種類型。它的最高位用於標識數據的符號:如果最高位為 1,表明這個數為負數;如果是0的則表明這個數為正數。那麽我們就來做個試驗驗證下,代碼如

從壹開始微服務 [ DDD ] 六 ║聚合 聚合根

前言 哈嘍大家週二好,上次咱們說到了實體與值物件的簡單知識,相信大家也是稍微有些瞭解,其實實體咱們平時用的很多了,基本可以和資料庫表進行聯絡,只不過值物件可能不是很熟悉,值物件簡單來說就是在DDD領域驅動設計中,為了更好的展示領域模型之間的關係,制定的一個物件,它沒有狀態和標識,目的就是為了表示一個值。今天

djangoORM介紹基本用法

  一、ORM介紹 1.什麼是ORM ORM 全拼Object-Relation Mapping. 中文意為 物件-關係對映. 在MVC/MVT設計模式中的Model模組中都包括ORM 2.ORM優勢 (1)只需要面

Spark Streaming實時處理筆記2—— 實時處理介紹

1 實時和離線計算對比 1.1 資料來源 離線:HDFS 歷史資料,資料量較大 實時:訊息佇列(Kafka) 1.2 處理過程 離線:Mapreduce 實時:Spark(DStream/SS) 1.3 處理速度 離

資料結構篇連結串列多項式的加法乘法。C++

連結串列多項式還算比較簡單的。 步驟分為 1.建立連結串列                  2.連結串列排序                  3.連結串列的自我化簡                   4.進行運算                  5.進行自我

java記憶體模型執行緒2

一、原子性、可見性與有序性 1.原子性 原子性操作包括read、load、asign、use、store和write 更大範圍的原子性保證:lock和unlock(倆者未開放),monitorenter和monitorexit(隱式的使用synchronized)

OC中UITableView自定義cell的使用2通過程式碼建立

在使用UITableView做開發時,常常會遇到 系統提供的樣式無法滿足專案需求的情況,這時就需要根據需求來自定義cell。 自定義cell有兩種方式:   · 通過xib自定義cell(適用於cell中子控制元件個數固定、cell樣式統一的結構,例如:商品的列表頁面)

大資料叢集搭建節點的網路配置過程

緊接著上一章來設定windows的vmnet8的ip地址和虛擬機器中centos的ip地址。 NAT虛擬網路的配置圖如下圖所示: 1、這裡根據VMware中得到的閘道器地址去設定vmnet8的ip地址。 閘道器地址檢視: 2、得到的閘道器地址後去

F#ASP.NET2使用F#實現基於事件的非同步模式

在上一篇文章中,我們的簡單討論了.NET中兩種非同步模型以及它們在異常處理上的區別,並且簡單觀察了ASP.NET MVC 2中非同步Action的編寫方式。從中我們得知,ASP.NET MVC 2的非同步Action並非使用了傳統基於Begin/End的非同步程式設計模型,而是另一種基於事件的非同步模式。此外

ASP.NET Aries 高階開發教程Excel匯入多表高階匯入配置

前言: 在面對Excel的各種複雜匯入情況中,多表匯入是很常見的情景。 今天就來寫一下多表匯入是如何配置的。 1、自定義匯入模板 怎麼自定義: 其實就是自己新建一個Excel了,把列頭都寫好。 不過有一些下拉選項,可能自己不好弄,比如使用者角色,是否這些要變成下拉可選操作,自己去資料庫複製

高等數學第十章 曲線積分曲面積分1對弧長、座標的曲線積分,格林公式及其應用

§10.1  對弧長的曲線積分 一、概念的引進 假設面內有一段曲線弧具有質量,在上任一點處的線密度為,且在上連續,與分別是弧的端點,現計算弧的質量。 在上任意地插入個分點 將分劃成個小弧段。對於第  個小弧段,由於線密度函式在上連續,當該小弧段的長度充分小時,它的質量近

JAVA 容器--比較大小比較重複2

承接上文: Comparable介面:針對排序list 問題:上面的演算法根據什麼確定容器中物件的“大小”順序? 所有可以“排序”的類都實現了java.lang.Comparable介面,Comp