Java IO流

tianjj-20180510發表於2020-11-10
  • IO流簡介:分別是InputStream(輸入流,又可以稱為讀)和OutputStream(輸出流,又可以稱為寫),輸入輸出都是相對於記憶體而言的,到記憶體中去是輸入,從記憶體中出來是輸出,例如:IO流可以完成記憶體和磁碟的互動
  • IO流分類(這幾個是最基本的流):在java.io包中有四個流:分別是InputStream(位元組輸入流)、OutputStream(位元組輸出流)、Reader(字元輸入流)、Writer(字元輸出流)
  • InputStream、OutputStream、Reader、Writer的共同點:
    它們都是抽象類
    它們都實現了Closeable介面,介面中有close()方法,那麼這四種流都有close()方法,說明它們是可以關閉的。
    輸出流都實現了Flushable介面,介面中有flush()方法,那麼這兩種流都有flush()方法,說明它們是可以重新整理的,這個重新整理是將管道里面剩餘的資料全部強行重新整理出去
    根據上面的兩個共同點可知:1、所有的流用完之後關閉 2、所有的輸出流最後重新整理一次在關閉
  • 位元組流:1次能讀取一個位元組(1個位元組byte是8個位元bit位),位元組流是萬能流,無論是聲音、視訊、圖片等都能讀
    字元流:1次能讀取兩個位元組,只能讀取普通文字,也就是以.txt、.java等結尾的文字檔案,連word檔案都讀不了
  • 怎麼區分位元組流和字元流?
    答:類名以stream結尾的都是位元組流;類名以reader或者writer結尾的都是字元流
  • IO流中需要了解的流(那幾個最基本流的部分子類):
    檔案專屬(最常用的就是這個,物件專屬流還是稍微比較常用的,其他的幾個不太常用):
    FileInputStream、FileOutputStream、FileReader、FileWriter
    自帶緩衝:
    BufferedInputStream、BufferedOutputStream、BufferedReader、BufferedWriter
    資料專屬:
    DataInputStream、DataOutputStream
    標準輸出:
    PrintStream(標準位元組輸出流)、PrintWriter(標準字元輸出流)
    物件專屬:
    ObjectInputStream、ObjectOutputStream
    轉換流(把位元組流轉換成字元流):
    InputStreamReader、OutputStreamWriter

  需要了解的流------檔案專屬流:

   FileInputStream、FileOutputStream介紹:
   FileInputStream:
       裡面有這麼幾個方法,分別是:read()、read(byte[] b)、read(byte[] b, int off, int len),

       read()就是一個一個位元組的從檔案中讀取,然後返回ASCII碼值,第一次呼叫會讀第一個,第二次使用會讀第二個,以此類推,當讀到檔案末尾的時候會返回-1;

       read(byte[] b)是按照位元組陣列的形式去讀取的,比如定義一個容量為4的位元組陣列,第一次讀取會讀取回來一個int值,這個值是讀取到的位元組數目,如果使用容量為4的位元組陣列去讀取6個位元組的檔案,如果讀取三次,返回的值分別是4、2、-1,如果沒有讀到值就會返回-1,但是byte陣列中的值是可以覆蓋的,第一次讀取四個的時候裡面有四個值,當第二次讀取的時候前面兩個被覆蓋了,但是後面兩個還是上一次讀的,這個時候從位元組陣列中取出我們想要的值就太麻煩了,將位元組陣列變成字串的過程中可以有一個String(byte[] bytes, int offset, int length),其中offset可以設定成0,後面的length可以設定成讀的時候返回的那個int值,這樣就會把byte陣列中我們想要的讀出來,捨棄那些我們不想要的,但是一次一次讀太麻煩了,可以使用while迴圈去讀,具體程式碼如下:

public class Test {
    public static void main(String[] args) {
        FileInputStream fileInputStream = null;
        try {
            fileInputStream = new FileInputStream("F:\\abc.txt");
            byte[] bytes = new byte[4];
            int read;
            while ((read=fileInputStream.read(bytes))!=-1){
                System.out.print(new String(bytes,0,read));
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fileInputStream!=null){
                try {
                    fileInputStream.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        }
    }
}

FileOutputStream:
這個新建的時候需要注意,裡面可以有兩個引數,第一個引數寫入檔案的那個路徑,第二個引數就是是否在原始檔案的後面追加,如果是true就進行追加,如果是false就是直接覆蓋,如果你不寫,預設就是false。

這個寫入的時候也有三種方式,分別是:write(int b)、write(byte[] b)、write(byte[] b, int off, int len),

第一種也是一個位元組一個位元組的寫入,雖然輸入的是數字,但是寫入的是這個數字對應的ASCII碼對應的字元,

第二種是寫入一個位元組陣列,我可以使用一個字串變成一個位元組陣列,然後寫入,

第三個就是把一個位元組陣列中的部分寫入,裡面的off是寫入的起始位置,第二個是寫入的長度,我拿第二種寫個例子如下:

public class Test {
    public static void main(String[] args) {
        FileOutputStream fileOutputStream = null;
        try {
            fileOutputStream = new FileOutputStream("F:\\abc.txt",true);
            String text = "abc";
            byte[] bytes = text.getBytes();
            fileOutputStream.write(bytes);
            fileOutputStream.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (fileOutputStream!=null){
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

 通過對上面FileInputStream和FileOutputStream的學習可以實現檔案的複製,程式碼如下:

public class Test {
    public static void main(String[] args) {
        FileInputStream input = null;
        FileOutputStream out = null;
        try {
            input = new FileInputStream("F:\\面試01.mp4");
            out = new FileOutputStream("F:\\newWork\\面試01.mp4");
            byte[] bytes = new byte[1024];
            int readNum;
            while ((readNum = input.read(bytes))!=-1){
                out.write(bytes, 0, readNum);
            }
            out.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (input!=null){
                try {
                    input.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (out!=null){
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

FileReader、FileWriter介紹:
說明:FileReader和FileWriter各自單獨使用的時候和上面的使用方法類似,可以去參考文件裡面看一下,這裡只把例子寫出來:
FileReader:

public class Test {
    public static void main(String[] args) {
        FileReader reader = null;
        try {
            reader = new FileReader("F:\\abc.txt");
            char[] chars = new char[512];//一個char是兩個位元組,512個字元就是1024個位元組,就相當於1kb
            int count;
            while ((count = reader.read(chars))!=-1){
                System.out.println(new String(chars,0,count));
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader!=null){
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

FilterWriter:

public class Test {
    public static void main(String[] args) {
        FileWriter writer = null;
        try {
            writer = new FileWriter("F:\\newWork\\abc.txt",true);
            String text = "abc";
            char[] chars = text.toCharArray();
            writer.write(chars);
            writer.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (writer!=null){
                try {
                    writer.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

然後寫兩個聯合使用實現賦值的功能,程式碼如下:

public class Test {
    public static void main(String[] args) {
        FileReader reader = null;
        FileWriter writer = null;
        try {
            reader = new FileReader("F:\\abc.txt");
            writer = new FileWriter("F:\\newWork\\abc.txt");
            char[] chars = new char[512];//一個char是兩個位元組,512個字元就是1024個位元組,就相當於1kb
            int count;
            while ((count = reader.read(chars))!=-1){
                writer.write(chars, 0, count);
            }
            writer.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader!=null){
                try {
                    reader.close();
                } catch (IOException e) {			
                    e.printStackTrace();
                }
            }
            if (writer!=null){
                try {
                    writer.close();
                } catch (IOException e) {			
                    e.printStackTrace();
                }
            }
        }
    }
}

需要了解的流------自帶緩衝流:

BufferedInputStream、BufferedOutputStream介紹:
和下面的這個類似,所以只講述下面這個

BufferedReader、BufferedWriter介紹:

BufferedReader:
簡單介紹:BufferedReader有一個readLine()方法,所以你可以不用提供char[]陣列,這個也是它自帶緩衝區的表現,在新建這個流的時候需要傳入一個引數,這個引數的型別是Reader型別的,但是Reader是抽象類,只能使用Reader的繼承來做,所以可以使用FileReader來做,所以說BufferedReder是基於FileReader的再次包裝,使用起來更加方便,其中FileReader被稱為節點流,而BufferedReder被稱為包裝流(處理流),根據上面的陳述可以知道包裝流並不是真正進行讀寫的流,只是起到包裝作用的流,包裝的目的是為了方便使用,並且注意在finally中關閉流的時候只需要關閉最外層的流,因為裡面的節點流會被包裝流自動關閉,具體程式碼如下:

public class Test {
    public static void main(String[] args) {
        BufferedReader reader = null;
        FileReader fileReader = null;
        try {
            fileReader = new FileReader("F:\\abc.txt");
            reader = new BufferedReader(fileReader);
            String text = null;
            while ((text=reader.readLine())!=null){
                System.out.println(text);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader!=null){
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

 BufferedWriter:

public class Test {
    public static void main(String[] args) {
        BufferedWriter writer =null;
        try {
            writer = new BufferedWriter(new FileWriter("F:\\newWork\\abc.txt",true));
            writer.write("123");
            writer.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (writer!=null){
                try {
                    writer.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

也可以將上面兩個合併起來做一個複製的功能,如下所示:

public class Test {
    public static void main(String[] args) {
        BufferedReader reader = null;
        BufferedWriter writer =null;
        try {
            reader = new BufferedReader(new FileReader("F:\\abc.txt"));
            writer = new BufferedWriter(new FileWriter("F:\\newWork\\abc.txt",true));
            String text = null;
            while ((text=reader.readLine())!=null){
                writer.write(text);
            }
            writer.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader!=null){
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (writer!=null){
                try {
                    writer.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

需要了解的流------資料專屬流:

DataInputStream、DataOutputStream介紹:
DataOutputStream:
說明:因為這種流是十分專業的,通過DataOutputStream寫的檔案必須使用DataInputStream來讀,並且還需要知道當時寫入的順序才能正常還原資料,這也就是為什麼先寫DataOutputStream的原因,程式碼如下:

public class Test06 {
    public static void main(String[] args) {
        DataOutputStream output = null;
        try {
        	// 這也是一個包裝流,裡面的那個是節點流
            output = new DataOutputStream(new FileOutputStream("F:\\newWork\\haha"));
            byte a = 97;
            short b = 1;
            char c = 'a';
            int d = 1;
            long e = 1l;
            float f = 1.0f;
            double g = 1.0;
            boolean h = true;
            output.writeByte(a);
            output.writeShort(b);
            output.writeChar(c);
            output.writeInt(d);
            output.writeLong(e);
            output.writeFloat(f);
            output.writeDouble(g);
            output.writeBoolean(h);
            output.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (output!=null){
                try {
                    output.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

DataInputStream:

public class Test07 {
    public static void main(String[] args) {
        DataInputStream input = null;
        try {
            input = new DataInputStream(new FileInputStream("F:\\newWork\\haha"));
            byte a = input.readByte();
            short b = input.readShort();
            char c = input.readChar();
            int d = input.readInt();
            long e = input.readLong();
            float f = input.readFloat();
            double g = input.readDouble();
            boolean h = input.readBoolean();
            System.out.println(a);
            System.out.println(b);
            System.out.println(c);
            System.out.println(d);
            System.out.println(e);
            System.out.println(f);
            System.out.println(g);
            System.out.println(h);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

需要了解的流------標準輸出流

PrintStream、PrintWriter介紹:
PrintStream:
說明: 一般使用的都是輸出流,可以改變System.out.println()的輸出方向,可以用作日誌的輸出

public class Test {
    public static void main(String[] args) {
        PrintStream print = null;
        print = System.out;
        print.println("hahah");
        try {
            print = new PrintStream(new FileOutputStream("F:\\newWork\\ming"));
            System.setOut(print);
            String date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS").format(new Date());
            System.out.println(date+"系統出現了問題");
            print.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            if (print!=null){
                print.close();
            }
        }
    }
}

需要了解的流------物件專屬流

ObjectInputStream、ObjectOutputStream介紹:
ObjectInputStream:

// 序列化過程:
public class Test09 {
    public static void main(String[] args) {
        ObjectOutputStream output = null;
        try {
            output = new ObjectOutputStream(new FileOutputStream("F:\\newWork\\Student"));
            Student student = new Student();
            student.setSno(1);
            student.setSname("李華");
            student.setSex(true);
            output.writeObject(student);
            output.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (output!=null){
                try {
                    output.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

ObjectOutputStream:

// 反序列化過程:
public class Test10 {
    public static void main(String[] args) {
        ObjectInputStream input = null;
        try {
            input = new ObjectInputStream(new FileInputStream("F:\\newWork\\Student"));
            Object student = input.readObject();
            System.out.println(student);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            if (input!=null){
                try {
                    input.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

需要了解的流------轉換流

InputStreamReader、OutputStreamWriter介紹:
OutputStreamWriter:

說明:由於上面學到了BufferedReader,所以和BufferedReader結合寫出這個例子,其中的InputStreamReader不僅是包裝流,也是節點流,它擔任了把位元組流轉換成字元流的任務,例子如下:

public class Test {
    public static void main(String[] args) {
        FileInputStream fileInputStream = null;
        InputStreamReader inputStreamReader = null;
        BufferedReader reader = null;
        try {
            fileInputStream = new FileInputStream("F:\\abc.txt");
            inputStreamReader = new InputStreamReader(fileInputStream);
            reader = new BufferedReader(inputStreamReader);
            String text = null;
            while ((text = reader.readLine())!=null){
                System.out.println(text);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader!=null){
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

OutputStreamWriter:

public class Test {
    public static void main(String[] args) {
        BufferedWriter writer =null;
        try {
            writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("F:\\newWork\\abc.txt",true)));
            writer.write("123");
            writer.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (writer!=null){
                try {
                    writer.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

 

相關文章