Java基礎教程:IO流與文件基礎

Java:IO流與文件基礎

說明:前端

  本章內容將會持續更新,你們能夠關注一下並給我提供建議,謝謝啦。java

走進流

什麼是流

  流:從源到目的地的字節的有序序列。數組

  

  在Java中,能夠從其中讀取一個字節序列的對象稱做 輸入流,能夠向其中寫入一個字節序列的對象稱做 輸出流
    ☑ 這些字節序列的來源能夠是:文件、網絡鏈接、內存塊等。
    ☑ 抽象類InputStream和OutputStream是構成輸入/輸出(I/O)的基礎。
    ☑ 由於面向字節的流不便於處理以Unicode形式存儲的信息(字符),因此從抽象類Reader 和 Writer中繼承出來一個專門處理字符流的類層次結構。
    ☑ 適配器類InputStreamReader將InputStream轉換爲Reader,OutputStreamWriter將OutputStream轉換爲Writer緩存

IO流家族體系:

  對流的分類網絡

☑ 依據流相對於程序的另外一個端點的不一樣:
  
☐ 節點流(全黃):以特定源(如磁盤文件、內存某區域或線程之間的管道)爲端點構造的輸入/輸出流
  ☐ 過濾流(半黃):以其餘已存在的流爲端點構造的輸入/輸出流。
☑ 依據流中的數據單位不一樣:
  
☐ 字節流:流中的數據以8位字節爲單位進行讀寫,以InputStream和OutputStream爲共同父類
  ☐ 字符流:流中的數據以16位字符爲單位進行讀寫,以Reader和Writer爲共同父類app

  家族體系圖(原創):dom

  

家族體系的頂層方法

 說明:學習

   頂層方法不是不少,可是須要咱們去記住,下面列出了全部的頂層方法,遇到問題是結合上圖和下表能夠清理思路。測試

  A.abstract class OutputStream

返回類型 方法及解釋
 void close()            關閉此輸出流並釋放與此流有關的全部系統資源。
 void flush()            刷新此輸出流並強制寫出全部緩衝的輸出字節。
 void write(byte[] b)            將 b.length 個字節從指定的 byte 數組寫入此輸出流。
 void write(byte[] b, int off, int len)            將指定 byte 數組中從偏移量 off 開始的 len 個字節寫入此輸出流。
abstract  void write(int b)            將指定的字節寫入此輸出流。

  B.abstract class 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 個數據字節讀入 byte 數組。
 void reset()            將此流從新定位到最後一次對此輸入流調用 mark 方法時的位置。
 long skip(long n)            跳過和丟棄此輸入流中數據的 n 個字節。

  C.abstract class Reader

返回類型 方法及解釋
abstract  void close()            關閉該流並釋放與之關聯的全部資源。
 void mark(int readAheadLimit)            標記流中的當前位置。
 boolean markSupported()            判斷此流是否支持 mark() 操做。
 int read()            讀取單個字符。
 int read(char[] cbuf)            將字符讀入數組。
abstract  int read(char[] cbuf, int off, int len)            將字符讀入數組的某一部分。
 int read(CharBuffer target)            試圖將字符讀入指定的字符緩衝區。
 boolean ready()            判斷是否準備讀取此流。
 void reset()            重置該流。
 long skip(long n)            跳過字符。

  D.abstract class Writer  

返回類型 方法及註釋
 Writer append(char c)            將指定字符添加到此 writer。
 Writer append(CharSequence csq)            將指定字符序列添加到此 writer。
 Writer append(CharSequence csq, int start, int end)            將指定字符序列的子序列添加到此 writer.Appendable。
abstract  void close()            關閉此流,但要先刷新它。
abstract  void flush()            刷新該流的緩衝。
 void write(char[] cbuf)            寫入字符數組。
abstract  void write(char[] cbuf, int off, int len)            寫入字符數組的某一部分。
 void write(int c)            寫入單個字符。
 void write(String str)            寫入字符串。
 void write(String str, int off, int len)            寫入字符串的某一部分。

 

輸出輸入流的嵌套

說明:

  單獨使用節點流的狀況在程序中較少出現。
  通常常經過過濾流將多個流套接在一塊兒,利用各類流的特性共同處理數據,套接的多個流構成了一個流鏈   ui

  優勢:

    方便數據的處理並提升處理的效率。

  

着重介紹的幾個過濾流:

  ☑ BufferedInputStream
    ☐ 在建立 BufferedInputStream 時,會建立一個內部緩衝區數組。
    ☐ 在讀取或跳過流中的字節時,可根據須要從包含的輸入流再次填充該內部緩衝區,一次填充多個字節。
  ☑ BufferedOuputStream
    ☐ 該類實現緩衝的輸出流。經過設置這種輸出流,應用程序就能夠將各個字節寫入底層輸出流中,而沒必要針對每次字節寫入調用底層系統。
  ☑ BufferedReader和BufferedWriter一樣也是提供緩存區。
  ☑ DataInputStream
    ☐ 包含用於讀取基本類型數據的所有接口

  說明:全部的這些在下面咱們都會從新強調並實現。

經常使用流

思惟導圖:

  

文件流

  文件流包括:

    ☐ FileReader/FileWriter類
    ☐ FileInputStream/FileOutputStream類

  建立文件流:

    ☐FileInputStream(File file) 
            經過打開一個到實際文件的鏈接來建立一個 FileInputStream,該文件經過文件系統中的 File 對象 file 指定。
    ☐FileInputStream(String name) 
            經過打開一個到實際文件的鏈接來建立一個 FileInputStream,該文件經過文件系統中的路徑名 name 指定。

  實例: 

  複製文件內容:

public class FileCopy{
        public static void main(String[] args) throws IOException{
                FileInputStream in=new FileInputStream("FileCopy.java");
                FileOutputStream out=new FileOutputStream("FileCopy.txt");
                int c;
                while( (c=in.read())!=-1)
                        out.write(c);
                in.close();
                out.close();
        }
}

緩存流

  說明:

    緩存流是過濾流,以InputStream/OutputStream爲前端流,並可指定緩衝區大小,如:
      public BufferedInputStream(InputStream in)
      public BufferedInputStream(InputStream in, int size)
    BufferedReader增長readLine()
    BufferedWriter增長newLine():寫入一個換行符。  

  演示:

public class BufferedIO{
    public static void main(String[] args) throws IOException{
        BufferedReader in=new BufferedReader(
                new FileReader("BufferedIO.java"));
        PrintWriter out=new PrintWriter( new BufferedWriter(
                new FileWriter("BufferedIO.txt")));
        String s;
        int linecnt=1;
        StringBuilder sb=new StringBuilder();
        while((s=in.readLine())!=null){
            sb.append(linecnt+":"+s+"\n");
            out.println(linecnt+":"+s);
            linecnt++;
        }
        in.close();
        out.close();
        System.out.print(sb.toString());
    }
}

說明:

  PrintWriter
  向文本輸出流打印對象的格式化表示形式,即在寫入的同時能夠對寫入的數據進行格式化。

數據流

數據流包括:

  DataInputStream/DataOutputStream類

讀寫基本數據類型的接口方法:

  

演示:

public class DataIO{
    public static void main(String[] args) throws IOException{
        DataOutputStream out=new DataOutputStream(
    new BufferedOutputStream(new FileOutputStream("data.txt")));
        out.writeBoolean(false); out.writeChar('c');
        out.writeByte(1); out.writeShort(2);
        out.writeInt(3); out.writeLong(4L);
        out.writeFloat(5.0f); out.writeDouble(6.0);
        out.writeUTF("hello world!"); out.close();

        DataInputStream in=new DataInputStream(
             new BufferedInputStream( new FileInputStream("data.txt")));
        System.out.println(in.readBoolean()+";"+in.readChar()+";");
        System.out.println(in.readByte()+";"+in.readShort()+";");
        System.out.println(+in.readInt()+";"+in.readLong());
        System.out.println(in.readFloat()+";"+in.readDouble()+";");
        System.out.println(in.readUTF()); in.close();
    }

  說明:

    ☑readUTF()與writeUTF()
      writeBytes(String)和writeChars(String)方法在DataInputStream中沒有對應的方法恢復出String
      用DataOutputStream寫字符串並使得DataInputStream能恢復出字符串的方法是使用writeUTF()和readUTF()
    ☑ UTF-8
      ASCII字符→單字節形式;非ASCII字符→多字節形式
      字符串長度→UTF-8字符串的前兩字節中
      Java中使用的是UTF-8的變體,UTF-8只是讀寫過程當中的字符串形式,程序中Unicode

標準IO:

標準輸入:鍵盤
標準輸出:加載Java程序的命令窗口
  Java在System類中定義了三個標準I/O流,是System類的三個靜態變量
    ☐System.in(public static final InputStream in):標準輸入流
    ☐System.out(public static final PrintStream out):標準輸出流
    ☐System.err(public static final PrintStream err):標準錯誤輸出流
  
程序從鍵盤讀入數據:
  ☐ int ch=System.in.read();
  ☐ System.in.read()從鍵盤緩衝區讀入一個字節的數據,返回的是整型值(低位字節爲輸入數據,高位字節全爲零)
  ☐ System.in.read()的執行使得整個程序被掛起,直到用戶從鍵盤輸入數據才繼續運行
  ☐ 從鍵盤逐行讀入:嵌套BufferedReader和InputStreamReader

實例:

public class StandardIO {
    public static void main(String[] args) {
        String s;
        BufferedReader in = new BufferedReader(
                       new InputStreamReader(System.in));
        System.out.println("Please input: ");
        try {
            s = in.readLine();
            while (!s.equals("exit")) {
                System.out.println(" read: " + s);
                s = in.readLine();
            }
            System.out.println("End of Inputting");
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

java.util.Scanner類:從控制檯讀取輸入

說明:
  Scanner sc=new Scanner(System.in);
    Scanner將控制檯輸入按照分隔符模式進行分割,分隔符模式默認爲匹配空格
  掃描結果經過各類next*()方法轉化爲不一樣類型的值
    next() 獲取一個字符串
    nextByte() 獲取一個byte類型的整數
    nextShort() 獲取一個short類型的整數
    nextInt() 獲取一個int類型的整數
    nextLong() 獲取一個long類型的整數
    nextFloat() 獲取一個float類型的數
    nextDouble() 獲取一個double類型的數
    nextLine() 獲取一行文本(即以回車鍵爲結束標誌)
輸入輸出的重定向:
  System.setIn(InputStream)
  System.setOut(PrintStream)
  System.setErr(PrintStream)

隨機存取文件

說明:

    到目前爲止所學習的Java流式輸入/輸出都是順序訪問流,即流中的數據必須按順序進行讀寫當須要隨機讀寫磁盤文件中的內容時,用RandomAccessFile類(既可對文件讀,又可對文件寫)

  RandomAccessFile與其餘頂層類的關係

  

  

構造方法:

  

構造方法摘要
RandomAccessFile(File file, String mode)            建立從中讀取和向其中寫入(可選)的隨機訪問文件流,該文件由 File 參數指定。
RandomAccessFile(String name, String mode)            建立從中讀取和向其中寫入(可選)的隨機訪問文件流,該文件具備指定名稱。
mode值 含意
"r" 以只讀方式打開。調用結果對象的任何 write 方法都將致使拋出 IOException。
"rw" 打開以便讀取和寫入。若是該文件尚不存在,則嘗試建立該文件。
"rws" 打開以便讀取和寫入,對於 "rw",還要求對文件的內容或元數據的每一個更新都同步寫入到底層存儲設備。
"rwd"   打開以便讀取和寫入,對於 "rw",還要求對文件內容的每一個更新都同步寫入到底層存儲設備。

操做:

文件指針操做
    long getFilePointer() //返回當前文件指針
    void seek(long pos) //文件指針定位到指定位置
    long length() //返回文件長度
    int skipBytes(int n) //從當前位置開始跳過n字節
讀操做(實現了DataInput接口)
    readBoolean(), readChar(), readInt(), readLong(), readFloat(), readDouble(), readLine(), readUTF()等
寫操做(實現了DataOutput接口)
    writeBoolean(), writeChar(), writeUTF(), writeInt(), writeLong(), writeFloat(), writeDouble()等

實例:

public class RandomAccessTest {
    public static void main(String[] args) throws IOException {
        long filePoint = 0;
        String s;
        RandomAccessFile file = new RandomAccessFile(
                    "RandomAccessTest.java", "r");
        long fileLength = file.length(); // 獲取文件長度
        while (filePoint < fileLength) {
            s = file.readLine(); // 讀一行字符,並移動文件指針
            System.out.println(s); // 輸出顯示讀入的一行字符
            file.skipBytes(5);
            filePoint = file.getFilePointer(); // 獲取當前文件指針
        }
        file.close();
    }
}

對象的串行化 

說明:
  將對象保存到外存,稱爲對象的永久化
  對象永久化的關鍵是將對象的狀態以一種串行格式表示出來,以便之後讀取可以將該對象重構出來。
  對Java對象的這一讀寫過程稱爲對象的串行化
常在下列狀況下使用:
  1.Java遠程方法調用(Remote Method Invocation)
  2.Java Bean / EJB
  3.對象永久化
實現串行化:
  • 用ObjectOutputStream/ObjectInputStream實現對象的串行化
    ◇ 經過ObjectOutputStream的writeObject方法將一個對象寫入到流中
      ▪ public final void writeObject(Object obj) throws IOException
    ◇ 經過ObjectInputStream的readObject方法將一個對象從對象流中讀出
      ▪ public final Object readObject() throws IOException, ClassNotFoundException
    ◇ ObjectOutputStream實現了java.io.DataOutput接口
    ◇ ectInputStream實現了java.io.DataInput接口
實例:

/*輸出對象*/
public class SerializeDate {
    SerializeDate( ){
        Date d = new Date( );
        try {
            ObjectOutputStream s= new ObjectOutputStream(
                    new FileOutputStream(「date.ser」));
            s.writeObject(d);
            s.close( );
        }catch( IOException e){
            e.printStackTrace( );
        }
    }
    public static void main(String args[]){
        SerializeDate b = new SerializeDate();
    }
} 
/*輸入對象*/
public class UnSerializeDate {
    Date d = null;
    UnSerializeDate() {
        try {
            ObjectInputStream s = new ObjectInputStream(
                    new FileInputStream("date.ser"));
            Object o=s.readObject();
            if(o instanceof Date)
                d = (Date) o; 
            s.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        UnSerializeDate us = new UnSerializeDate();
        System.out.println(us.d.toString());
    }
}


注意:
  一個類只有實現了Serializable接口,其對象纔是可串行化的

(未完待續.....)

相關文章
相關標籤/搜索