IO,對象傳輸的基石(一)

2020-12-02 標準Java

一、前言

二、文件字節流

2.1 概述

Java中,凡是涉及到Java程序的輸入輸出,一般都逃不過IO流,Java中的IO包括BIO和NIO,其中BIO只要是以四大基流基礎的各種各樣的阻塞流。BIO的四大基流是:InputStream OutputStream Reader Writer,但是它們都是抽象類,不能實例化對象來完成輸入輸出操作,直接使用的是它們的子類,本部分中,使用FileInputStream和FileOutputStream就可以完成輸入輸出。

BIO的四大基流

輸入流輸出流字節流字節輸入流InputStream字節輸出流OutputStream字符流字符輸入流Reader字符輸出流Writer

使用BIO流的四個步驟:
1):創建源或者目標對象(挖井).
輸入操作: 把文件中的數據流向到程序中,此時文件是源,程序是目標.
輸出操作: 把程序中的數據流向到文件中,此時文件是目標,程序是源.
2):創建IO流對象(水管).
輸入操作: 創建輸入流對象.
輸出操作: 創建輸出流對象.
3):具體的IO操作.
輸入操作: 輸入流對象的read方法.
輸出操作: 輸出流對象的write方法.
4):關閉資源(勿忘). 一旦資源關閉之後,就不能使用流對象了,否則報錯.
輸入操作: 輸入流對象.close();
輸出操作: 輸出流對象.close().

關於BIO流的方向:
讀進來,寫出去。
讀進來是指:從文件、網絡、壓縮包或其他數據源到Java程序;
寫出去是指:從Java程序到文件、網絡、壓縮包或其他輸出目標。

2.2 文件字節輸入流FileInputStream、文件字節輸出流FileOutputStream

注意,這裡指的文件僅為純文本文件txt,不包括doc docx等文件。

2.2.1 文件字節輸出流

package mypackage;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.io.OutputStream;//文件字節輸出流public class Test { public static void main(String[] args) throws IOException { File target = new File("stream.txt");// 程序可以自動創建txt文件 OutputStream outputStream = new FileOutputStream(target); // 四大基流不能直接實例化對象,實例化對象還要具體IO類,這裡是FileOutputStream outputStream.write("hello world!".getBytes(), 0, 12); outputStream.close(); }}

輸出1:

小結1:文件字節輸出流,將文本從程序輸出到stream.txt中。

2.2.2 文件字節輸入流

package mypackage2;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;//文件字節輸入流public class Test { public static void main(String[] args) throws IOException { File file = new File("stream.txt"); InputStream inputStream = new FileInputStream(file); byte[] buffer = new byte[1024]; int len = -1; while ((len = inputStream.read(buffer)) != -1) { String string = new String(buffer, 0, len); // 每次讀入一個緩衝大小然後輸出 System.out.println(string); } inputStream.close(); }}

輸出2:

hello world!

小結2:文件字節輸入流,將文本從stream.txt輸入到程序中,並列印到控制臺。

2.2.3 先讀入再寫出 從myStream.txt讀入,寫出到myStream_copy.txt中

package mypackage3;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;public class Test { // 先讀入再寫出 從myStream.txt讀入,寫出到myStream_copy.txt中 // 從myStream.txt中讀入數據,然後寫入到myStream_copy.txt中 public static void main(String[] args) throws IOException { File srcFile = new File("myStream.txt"); // 源文件 File destFile = new File("myStream_copy.txt");// 目標文件 InputStream inputStream = new FileInputStream(srcFile); OutputStream outputStream = new FileOutputStream(destFile); byte[] buffer = new byte[10]; int len = -1; while ((len = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, len); } inputStream.close(); outputStream.close(); }}

輸出3:

小結3:先讀入再寫出,從myStream.txt讀入,寫出到myStream_copy.txt中,將輸入輸出流一起使用。

2.2.4 先寫出再讀入 寫出到FileStream.txt,在讀入到程序中,列印出來

package mypackage4;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;public class Test { // 先寫出再讀入 寫出到FileStream.txt,在讀入到程序中,列印出來 public static void main(String[] args) throws IOException { File srcFile = new File("FileStream.txt");// 程序可以自動創建txt文件 File destFile = new File("FileStream.txt"); OutputStream outputStream = new FileOutputStream(srcFile); // 四大基流不能直接實例化對象,實例化對象還要具體IO類,這裡是FileOutputStream InputStream inputStream = new FileInputStream(destFile); outputStream.write("hello world!".getBytes(), 0, 12); byte[] buffer = new byte[1024]; int len = -1; while ((len = inputStream.read(buffer)) != -1) { String string = new String(buffer, 0, len); // 每次讀入一個緩衝大小然後輸出 System.out.println(string); } outputStream.close(); inputStream.close(); }}

輸出4:

hello world!

小結4:先寫出再讀入,寫出到FileStream.txt,再讀入到程序中,列印出來,輸入輸出流一起使用。

2.3 面試金手指:文件字節輸入流 + 文件字節輸出流

Java中,凡是涉及到Java程序的輸入輸出,一般都逃不過IO流,Java中的IO包括BIO和NIO,其中BIO只要是以四大基流基礎的各種各樣的阻塞流。BIO的四大基流是:InputStream OutputStream Reader Writer,但是它們都是抽象類,不能實例化對象來完成輸入輸出操作,直接使用的是它們的子類,本部分中,使用FileInputStream和FileOutputStream就可以完成輸入輸出。

BIO的四大基流

使用BIO流的四個步驟:
1):創建源或者目標對象(挖井).
輸入操作: 把文件中的數據流向到程序中,此時文件是源,程序是目標.
輸出操作: 把程序中的數據流向到文件中,此時文件是目標,程序是源.
2):創建IO流對象(水管).
輸入操作: 創建輸入流對象.
輸出操作: 創建輸出流對象.
3):具體的IO操作.
輸入操作: 輸入流對象的read方法.
輸出操作: 輸出流對象的write方法.
4):關閉資源(勿忘). 一旦資源關閉之後,就不能使用流對象了,否則報錯.
輸入操作: 輸入流對象.close();
輸出操作: 輸出流對象.close().

關於BIO流的方向:
讀進來,寫出去。
讀進來是指:從文件、網絡、壓縮包或其他數據源到Java程序;
寫出去是指:從Java程序到文件、網絡、壓縮包或其他輸出目標。

三、文件字符流

3.1 引入:字符流

問題1:為什麼有了字節流還要有字符流呢?
回答1:亂碼問題引入字符流:上面操作的文本都是英文文本,不存在任何亂碼問題,如果操作中文文本,字節流存在亂碼問題,用字符流解決。使用字節流操作漢字或特殊的符號語言的時候,容易亂碼,建議使用字符流.

問題2:為什麼有了文件字節流還要有文件字符流呢?
回答2:字符流是字節流的補充:先有字節流,後有字符流,字符流是對字節流的補充.
使用記事本打開某個文件,可以看到內容的就是文本文件,否則可以理解二進位.
一般的,操作二進位文件(圖片,音頻,視頻等)必須使用字節流.
一般的,操作文本文件使用字符流.
如果不清楚是哪一類型文件,使用字節流.

3.2 字符流

3.2.1 文件字符輸入流

package mypackage; import java.io.File;import java.io.FileReader;import java.io.IOException;import java.io.Reader; //字符輸入流public class Test { public static void main(String[] args) throws IOException { File srcFile = new File("china.txt"); Reader reader = new FileReader(srcFile); char[] buffer = new char[1024]; int len = -1; while ((len = reader.read(buffer)) != -1) { System.out.println(buffer); } reader.close(); } }

輸出1:

Java程式設計師就業前景好,薪資高!一起來學習Java吧!

小結1:文件字符輸入流,將文本內容從china.txt讀入程序並列印出來。

3.2.2 文件字符輸出流

package mypackage2; import java.io.File;import java.io.FileWriter;import java.io.IOException;import java.io.Writer; //字符輸出流public class Test { public static void main(String[] args) throws IOException { File file = new File("china.txt"); Writer writer = new FileWriter(file, false); writer.write("Java程式設計師就業前景好,薪資高!"); writer.write("\n"); writer.write("一起來學習Java吧!"); writer.flush(); writer.close(); } }

輸出2:

小結2:文件字符輸出流,將程序的文本寫出到china.txt中。

2.2.3 先輸入後輸出 從mychina.txt文件輸入,輸出到mychina_copy.txt文件

package mypackage3; import java.io.File;import java.io.FileNotFoundException;import java.io.FileReader;import java.io.FileWriter;import java.io.Reader;import java.io.Writer; //先輸入後輸出 從mychina.txt文件輸入,輸出到mychina_copy.txt文件public class Test { public static void main(String[] args) throws Exception { File srcFile = new File("mychina.txt"); File destfile = new File("mychina_copy.txt"); Reader reader = new FileReader(srcFile); Writer writer = new FileWriter(destfile, false); char[] buffer = new char[1024]; int len = -1; while ((len = reader.read(buffer)) != -1) { writer.write(buffer, 0, len); } reader.close(); writer.close(); } }

輸出3:

小結3:先輸入後輸出,從mychina.txt文件輸入,輸出到mychina_copy.txt文件。

2.2.4 先輸出後輸入 先寫出到mychinaChar,再從mychinaChar讀入程序,列印到控制臺:

package mypackage4; import java.io.File;import java.io.FileReader;import java.io.FileWriter;import java.io.Reader;import java.io.Writer; //先輸出後輸入 先寫出到mychinaChar,再從mychinaChar讀入程序,列印到控制臺public class Test { public static void main(String[] args) throws Exception { File targetFile = new File("mychinaChar.txt"); Writer writer = new FileWriter(targetFile, false); Reader reader = new FileReader(targetFile); // 寫出到mychinaChar writer.write("Java程式設計師就業前景好,薪資高!"); writer.write("\n"); writer.write("一起來學習Java吧!"); writer.flush(); // 字符寫出 一定要刷新 char[] buffer = new char[1024]; int len = -1; while ((len = reader.read(buffer)) != -1) { System.out.println(buffer); } reader.close(); writer.close(); } }

輸出4:

Java程式設計師就業前景好,薪資高!一起來學習Java吧!

小結4:先輸出後輸入,先寫出到mychinaChar,再從mychinaChar讀入程序,列印到控制臺!

3.3 面試金手指:文件字符輸入流 + 文件字符輸出流

JavaIO流——文件字符流,包括文件字符輸入流FileReader,文件字符輸出流FileWriter,這兩種流聯合起來完成最基本的字符操作。

四、提交效率:緩衝流 + byte數組

4.1 引入:緩衝流 + byte數組,兩種提高IO效率的方式

比較四種方式下,對於同一文件stream.txt,JavaIO流輸入輸出操作的總時間。分別是:不使用緩衝流不使用byte數組(代碼1),使用緩衝流(代碼2),使用byte數組(代碼3),同時使用緩衝流和byte數組(代碼4)。

注意:txt內容一定要足夠大,否則效果不明顯,IO流一下子就操作完了

4.2 緩衝流 + byte數組

4.2.1 不使用緩衝流不使用byte數組:直接使用文件字節輸入和文件字節輸出

package mypackage; import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.InputStream;import java.io.OutputStream;import java.io.Writer; //用緩衝流和緩衝數組提高讀寫效率 要將文本內容弄長一些效果才明顯 同時擁有讀入流和寫出流//先讀入後寫出 從stream.txt中讀入,寫出到stream_copy.txt中public class Test { public static void main(String[] args) throws Exception { long begin = System.currentTimeMillis(); File srcFile = new File("stream.txt"); File destFile = new File("stream_copy.txt"); InputStream inputStream = new FileInputStream(srcFile); OutputStream outputStream = new FileOutputStream(destFile); int len = -1; while ((len = inputStream.read()) != -1) { outputStream.write(len); } inputStream.close(); outputStream.close(); System.out.println(System.currentTimeMillis() - begin); } }

輸出1:

640

小結1:不使用緩衝流不使用byte數組,IO流操作速度最慢,640毫秒。

4.2.2 使用緩衝流包一層:緩衝流包裹文件字節輸入和文件字節輸出

package mypackage2緩衝流; import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.InputStream;import java.io.OutputStream;import java.io.Writer; //用緩衝流和緩衝數組提高讀寫效率 要將文本內容弄長一些效果才明顯 同時擁有讀入流和寫出流//先讀入後寫出 從stream.txt中讀入,寫出到stream_copy.txt中public class Test { public static void main(String[] args) throws Exception { long begin = System.currentTimeMillis(); File srcFile = new File("stream.txt"); File destFile = new File("stream_copy.txt"); InputStream inputStream = new BufferedInputStream(new FileInputStream(srcFile)); OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(destFile)); int len = -1; while ((len = inputStream.read()) != -1) { outputStream.write(len); } inputStream.close(); outputStream.close(); System.out.println(System.currentTimeMillis() - begin); } }

輸出2:

8

小結2:使用緩衝流,加快了速度。

4.2.3 使用byte數組:文件字節讀取和文件字節寫出都是用byte數組

package mypackage3_1024數組; import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.InputStream;import java.io.OutputStream;import java.io.Writer; //用緩衝流和緩衝數組提高讀寫效率 要將文本內容弄長一些效果才明顯 同時擁有讀入流和寫出流//先讀入後寫出 從stream.txt中讀入,寫出到stream_copy.txt中public class Test { public static void main(String[] args) throws Exception { long begin = System.currentTimeMillis(); File srcFile = new File("stream.txt"); File destFile = new File("stream_copy.txt"); InputStream inputStream = new FileInputStream(srcFile); OutputStream outputStream = new FileOutputStream(destFile); byte[] buffer = new byte[1024]; // 每次1024個 int len = -1; while ((len = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, len); } inputStream.close(); outputStream.close(); System.out.println(System.currentTimeMillis() - begin); } }

輸出3:

1

小結3:使用了byte數組,加快了速度。

4.2.4 同時使用緩衝流和byte數組:緩衝流包一層,然後得到的緩衝流的讀入和寫出都用byte數組

package mypackage4緩衝流_1024數組; import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.InputStream;import java.io.OutputStream;import java.io.Writer; //用緩衝流和緩衝數組提高讀寫效率 要將文本內容弄長一些效果才明顯 同時擁有讀入流和寫出流//先讀入後寫出 從stream.txt中讀入,寫出到stream_copy.txt中public class Test { public static void main(String[] args) throws Exception { long begin = System.currentTimeMillis(); File srcFile = new File("stream.txt"); File destFile = new File("stream_copy.txt"); InputStream inputStream = new BufferedInputStream(new FileInputStream(srcFile)); OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(destFile)); byte[] buffer = new byte[1024]; // 每次1024個 int len = -1; while ((len = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, len); } inputStream.close(); outputStream.close(); System.out.println(System.currentTimeMillis() - begin); } }

輸出4:

1

小結4:同時使用緩衝流和byte數組,大大加快速度。

4.3 面試金手指:緩衝流 + byte數組

緩衝流和byte數組(字節流byte數組,字符流char數組)都可以加速IO流讀寫速度,本程序(代碼1、代碼2、代碼3、代碼4)中由於stream.txt文本不夠大,所以效果不是很明顯。實際上,第四種方式,同時使用緩衝流和byte數組,速度是最快的,讀者知道就好。
(1)不使用緩衝流不使用byte數組:直接使用文件字節輸入和文件字節輸出;
(2)使用緩衝流包一層:緩衝流包裹文件字節輸入和文件字節輸出;
(3)使用byte數組:文件字節讀取和文件字節寫出都是用byte數組;
(4)同時使用緩衝流和byte數組:緩衝流包一層,然後得到的緩衝流的讀入和寫出都用byte數組.

五、字符編碼

5.1 編碼和解碼

編碼: 把字符串轉換為byte數組.
解碼: 把byte數組轉換為字符串.
一定要保證編碼和解碼的字符相同,否則亂碼.

5.2 代碼:編碼和解碼

5.2.1 字符串編碼為byte數組,byte數組解碼為字符串

代碼1:

package mypackage; import java.util.Arrays; //編碼: 把字符串轉換為byte數組.//解碼: 把byte數組轉換為字符串.//一定要保證編碼和解碼的字符相同,否則亂碼.public class Test { public static void main(String[] args) throws Exception { String mString = "Java程式設計師就業前景好,薪資高"; // 字符串 byte[] data = mString.getBytes("UTF-8"); // 字符串變為byte數組,編碼 // String ret=new String(data,"GBK"); //使用GBK解碼亂碼,一定要保證編碼和解碼的字符相同,否則亂碼. // System.out.println(ret); String ret = new String(data, "UTF-8"); // byte數組變為字符串,解碼 System.out.println(ret); // 列印解碼 } }

輸出1:

Java程式設計師就業前景好,薪資高

小結1:一定要保證編碼和解碼的字符相同,否則亂碼.

5.2.2 困境:字符串UTF-8編碼為byte數組,byte數組GBK解碼為字符串

代碼2——困境:

package mypackage1; //編碼: 把字符串轉換為byte數組.//解碼: 把byte數組轉換為字符串.//一定要保證編碼和解碼的字符相同,否則亂碼.public class Test { public static void main(String[] args) throws Exception { String mString = "Java程式設計師就業前景好,薪資高"; byte[] data = mString.getBytes("UTF-8"); // 編碼UTF-8 String ret = new String(data, "GBK"); // 解碼GBK } }

小結2:這裡編碼UTF-8,但是解碼GBK,接下來怎麼破,且看代碼3.

5.2.3 解決:字符串UTF-8編碼為byte數組,byte數組GBK解碼為字符串,然後,字符串再次GBK編碼一次得到byte數組,最後byte數組UTF-8解碼一次得到字符串,列印出來

代碼3——破解代碼2的困境:

package mypackage1; //編碼: 把字符串轉換為byte數組.//解碼: 把byte數組轉換為字符串.//一定要保證編碼和解碼的字符相同,否則亂碼.public class Test { public static void main(String[] args) throws Exception { String mString = "Java程式設計師就業前景好,薪資高"; byte[] data = mString.getBytes("UTF-8"); // 編碼UTF-8 String ret = new String(data, "GBK"); // 解碼GBK data = ret.getBytes("GBK"); // 編碼 ret = new String(data, "UTF-8"); System.out.println(ret); } }

輸出3:

Java程式設計師就業前景好,薪資高

小結3:所謂的編碼解碼,無非就是正過來一次,反過來一次罷了,這裡編碼UTF-8,解碼GBK,接下來只能編碼GBK,解碼UTF-8破解,就是破解方法和前面的編碼解碼反過來就好了。

5.3 面試金手指:字符編碼

字符編碼:只要記住兩條,
第一,編碼和解碼的字符要相同,否則亂碼;
第二,不管前面編碼解碼多麼複雜,只要反過來操作就可以還原內容,列印出來。
2.1 字符串編碼為byte數組,byte數組解碼為字符串;
2.2 困境:字符串UTF-8編碼為byte數組,byte數組GBK解碼為字符串;
2.3 解決:字符串UTF-8編碼為byte數組,byte數組GBK解碼為字符串,然後,字符串再次GBK編碼一次得到byte數組,最後byte數組UTF-8解碼一次得到字符串,列印出來。

六、轉換流

6.1 概述:轉換流,將字節流轉換為字符流

JavaIO流——轉換流,將字節流轉換為字符流。
InputStreamReader:把字節輸入流轉成字符輸入流.
OutputStreamWriter:把字節輸出流轉成字符輸出流.
為什麼有字節轉字符流,沒有字符轉字節流?
字節流可以操作一切文件(純文本文件/二進位文件).字符流是用來操作中文純文本使用的,本身是對字節流的增強.所以字節流轉換為字符流是安全的,字符流轉換為字節流不一定安全,所以沒有字符流轉換
為字節流,個人理解,非官方解釋,皮!

解釋上圖:
字符流是接口,轉化流是字符流的非抽象子類,可以實例化對象,但是使用字節流對象作為構造器參數,然後文件字符流和是轉換流的子類,可以單獨使用

6.2 代碼:轉換流,將字節流轉換為字符流,一段代碼,包裹使用,轉換流包裹文件字節輸入流和文件字節輸出流

先讀入originStream.txt內容到程序,再將內容寫出到targetStream.txt:

package mypackage_輸入流輸出流; //轉換流:把字節流轉成字符流: //InputStreamReader:把字節輸入流轉成字符輸入流.//OutputStreamWriter:把字節輸出流轉成字符輸出流.//為什麼有字節轉字符流,沒有字符轉字節流.// 字節流可以操作一切文件(純文本文件/二進位文件).// 字符流是用來操作中文純文本使用的,本身是對字節流的增強. import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.io.Reader;import java.io.Writer; //先讀入originStream.txt內容到程序,再將內容寫出到targetStream.txtpublic class Test { public static void main(String[] args) throws Exception { File originStream = new File("originStream.txt"); File targetStream = new File("targetStream.txt"); Reader reader = new InputStreamReader(new FileInputStream(originStream)); Writer writer = new OutputStreamWriter(new FileOutputStream(targetStream)); char[] buffer = new char[1024]; // 字節流用byte[1024]作為緩衝,字符流用char[1024]作為緩衝 // 注意,這個緩衝buffer數組大小是任意的,可以是5,可以是10,可以是1000,可以是1024 僅表示一次讀寫的字節數或字符數 int len = -1; while ((len = reader.read(buffer)) != -1) { writer.write(buffer, 0, len); } reader.close(); writer.close(); } }

輸入:

輸出1:

小結1:上面的邏輯上沒有特別之處,就是輸入流+輸出流,先讀入originStream.txt內容到程序,再將內容寫出到targetStream.txt。演示的意義在於加入了轉換流,將字符操作變為字節操作,用於完成輸入輸出。

6.3 面試金手指:轉換流,將字節流轉換為字符流

Java BIO中的轉換流,將字節流轉換為字符流,為我們提供了一種字符操作變為字節操作,進而實現輸入輸出的方式。
代碼演示的邏輯上沒有特別之處,就是輸入流+輸出流,先讀入originStream.txt內容到程序,再將內容寫出到targetStream.txt。演示的意義在於加入了轉換流,將字符操作變為字節操作,用於完成輸入輸出。

七、內存流/數組流/字符串流

7.1 概述:內存流

JavaIO流——內存流,內存流實際是數組流/字符串流
內存流(數組流):適配器模式:
1):字節內存流: ByteArrayInputStream/ByteArrayOutputStream 先將數據先臨時存在byte數組中,待會再從byte數組中獲取出來.
2):字符內存流: CharArrayReader/CharArrayWriter 先將數據先臨時存在char數組中,待會再從char數組中獲取出來.
3):字符串流:StringReader/StringWriter 先將數據(字符串)從程序寫出到stringwriter中,即臨時存儲到字符串中,然後將stringwriter中的內容讀入程序並列印出來。

7.2 代碼:內存流,在內存中呆一會,三段代碼,單獨使用,ByteArrayXxx CharArrayXxx,StringXxx

7.2.1 字節內存流

package mypackage_字節數組流; import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream; //內存流(數組流):適配器模式:// 把數據先臨時存在數組中,待會再從數組中獲取出來.// 1):字節內存流: ByteArrayInputStream/ByteArrayOutputStream 數據臨時存放到數組中// 2):字符內存流: CharArrayReader/CharArrayWriter 數據臨時存放到數組中// 3):字符串流:StringReader/StringWriter(把數據臨時存儲到字符串中)//字節內存流——字節數組流 內存流實際是數組流,字節內存流和字符內存流都是將數據存放到數組中,字符串流將數據存放到字符串中。public class Test { public static void main(String[] args) throws Exception { // 數據從程序寫出到內存(即數組) 內存字節輸出流 ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); byteArrayOutputStream.write("Java is the best language".getBytes()); byte[] buffer = byteArrayOutputStream.toByteArray(); byteArrayOutputStream.close(); // 數據從內存(即數組)讀入到程序 內存字節輸入流 ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(buffer); byte[] _bytes = new byte[1024];// 字節緩衝為byte數組 int len = -1; while ((len = byteArrayInputStream.read(_bytes)) != -1) { System.out.println(new String(_bytes, 0, len)); } byteArrayInputStream.close(); }}

輸出1:

Java is the best language

小結1:這裡演示字節內存流,先將「Java is the best language」從程序寫出到內存數組buffer中,然後將buffer數組中的內容讀入程序並列印出來。

7.2.2 字符內存流

package mypackage_字符數組流; import java.io.CharArrayReader;import java.io.CharArrayWriter; public class Test { public static void main(String[] args) throws Exception { // 數據從程序寫出到內存(即數組) CharArrayWriter charArrayWriter = new CharArrayWriter(); charArrayWriter.write("Java程式設計師就業前景好,薪資高!一起來學習Java吧!"); char[] buffer = charArrayWriter.toCharArray(); charArrayWriter.close(); // 數據從內存(即數組)讀入到程序 CharArrayReader charArrayReader = new CharArrayReader(buffer); char[] _chars = new char[1024];// 字節緩衝為byte數組 int len = -1; while ((len = charArrayReader.read(_chars)) != -1) { System.out.println(new String(_chars, 0, len)); } charArrayReader.close(); } }

輸出2:

Java程式設計師就業前景好,薪資高!一起來學習Java吧!

小結2:這裡演示字符內存流,先將「Java程式設計師就業前景好,薪資高!一起來學習Java吧!」從程序寫出到內存數組buffer中,然後將buffer數組中的內容讀入程序並列印出來。不同的是,字節內存流用byte數組,字符內存流用char數組。

7.2.3 字符串流

package 字符串流; import java.io.StringReader;import java.io.StringWriter; public class Test { public static void main(String[] args) throws Exception { // 數據從程序寫出到內存(即數組) StringWriter stringWriter = new StringWriter(); stringWriter.write("Java程式設計師就業前景好,薪資高!一起來學習Java吧!"); // 數據從內存(即數組)讀入到程序 StringReader stringReader = new StringReader(stringWriter.toString()); char[] _chars = new char[1024];// 字節緩衝為byte數組 int len = -1; while ((len = stringReader.read(_chars)) != -1) { System.out.println(new String(_chars, 0, len)); } stringReader.close(); stringWriter.close(); }}

輸出3:

Java程式設計師就業前景好,薪資高!一起來學習Java吧!

小結3:這裡演示字符串流,先將「Java程式設計師就業前景好,薪資高!一起來學習Java吧!」從程序寫出到stringwriter中,然後將stringwriter中的內容讀入程序並列印出來。

7.3 面試金手指:內存流/數組流/字符串流

Java內存流分為三種字節內存流、字符內存流、字符串流,都分別有輸入流和輸出流,
1):字節內存流: ByteArrayInputStream/ByteArrayOutputStream 先將數據先臨時存在byte數組中,待會再從byte數組中獲取出來.
2):字符內存流: CharArrayReader/CharArrayWriter 先將數據先臨時存在char數組中,待會再從char數組中獲取出來.
3):字符串流:StringReader/StringWriter 先將數據(字符串)從程序寫出到stringwriter中,即臨時存儲到字符串中,然後將stringwriter中的內容讀入程序並列印出來。

八、面試金手指

8.1 文件字節輸入流 + 文件字節輸出流

Java中,凡是涉及到Java程序的輸入輸出,一般都逃不過IO流,Java中的IO包括BIO和NIO,其中BIO只要是以四大基流基礎的各種各樣的阻塞流。BIO的四大基流是:InputStream OutputStream Reader Writer,但是它們都是抽象類,不能實例化對象來完成輸入輸出操作,直接使用的是它們的子類,本部分中,使用FileInputStream和FileOutputStream就可以完成輸入輸出。

BIO的四大基流

使用BIO流的四個步驟:
1):創建源或者目標對象(挖井).
輸入操作: 把文件中的數據流向到程序中,此時文件是源,程序是目標.
輸出操作: 把程序中的數據流向到文件中,此時文件是目標,程序是源.
2):創建IO流對象(水管).
輸入操作: 創建輸入流對象.
輸出操作: 創建輸出流對象.
3):具體的IO操作.
輸入操作: 輸入流對象的read方法.
輸出操作: 輸出流對象的write方法.
4):關閉資源(勿忘). 一旦資源關閉之後,就不能使用流對象了,否則報錯.
輸入操作: 輸入流對象.close();
輸出操作: 輸出流對象.close().

關於BIO流的方向:
讀進來,寫出去。
讀進來是指:從文件、網絡、壓縮包或其他數據源到Java程序;
寫出去是指:從Java程序到文件、網絡、壓縮包或其他輸出目標。

8.2 文件字符輸入流 + 文件字符輸出流

JavaIO流——文件字符流,包括文件字符輸入流FileReader,文件字符輸出流FileWriter,這兩種流聯合起來完成最基本的字符操作。

8.3 提高IO效率:緩衝流 + byte數組

緩衝流和byte數組(字節流byte數組,字符流char數組)都可以加速IO流讀寫速度,本程序(代碼1、代碼2、代碼3、代碼4)中由於stream.txt文本不夠大,所以效果不是很明顯。實際上,第四種方式,同時使用緩衝流和byte數組,速度是最快的,讀者知道就好。
(1)不使用緩衝流不使用byte數組:直接使用文件字節輸入和文件字節輸出;
(2)使用緩衝流包一層:緩衝流包裹文件字節輸入和文件字節輸出;
(3)使用byte數組:文件字節讀取和文件字節寫出都是用byte數組;
(4)同時使用緩衝流和byte數組:緩衝流包一層,然後得到的緩衝流的讀入和寫出都用byte數組.

8.4 編碼解碼

字符編碼:只要記住兩條,
第一,編碼和解碼的字符要相同,否則亂碼;
第二,不管前面編碼解碼多麼複雜,只要反過來操作就可以還原內容,列印出來。
2.1 字符串編碼為byte數組,byte數組解碼為字符串;
2.2 困境:字符串UTF-8編碼為byte數組,byte數組GBK解碼為字符串;
2.3 解決:字符串UTF-8編碼為byte數組,byte數組GBK解碼為字符串,然後,字符串再次GBK編碼一次得到byte數組,最後byte數組UTF-8解碼一次得到字符串,列印出來。

8.5 轉換流,字節輸入輸出轉換為字符輸入輸出

JavaIO流——轉換流,將字節流轉換為字符流。
InputStreamReader:把字節輸入流轉成字符輸入流.
OutputStreamWriter:把字節輸出流轉成字符輸出流.
為什麼有字節轉字符流,沒有字符轉字節流?
字節流可以操作一切文件(純文本文件/二進位文件).字符流是用來操作中文純文本使用的,本身是對字節流的增強.所以字節流轉換為字符流是安全的,字符流轉換為字節流不一定安全,所以沒有字符流轉換為字節流,個人理解,非官方解釋,皮!

字符流是接口,轉化流是字符流的非抽象子類,可以實例化對象,但是使用字節流對象作為構造器參數,然後文件字符流和是轉換流的子類,可以單獨使用

Java BIO中的轉換流,將字節流轉換為字符流,為我們提供了一種字符操作變為字節操作,進而實現輸入輸出的方式。
代碼演示的邏輯上沒有特別之處,就是輸入流+輸出流,先讀入originStream.txt內容到程序,再將內容寫出到targetStream.txt。演示的意義在於加入了轉換流,將字符操作變為字節操作,用於完成輸入輸出。

8.6 內存流,讓數據在內存中呆一會,內存字節輸入輸出 + 內存字符輸入輸出 + 字符串輸入輸出

Java內存流就是讓數據在內存中呆一會,分為三種字節內存流、字符內存流、字符串流,都分別有輸入流和輸出流,
1):字節內存流: ByteArrayInputStream/ByteArrayOutputStream 先將數據先臨時存在byte數組中,待會再從byte數組中獲取出來.
2):字符內存流: CharArrayReader/CharArrayWriter 先將數據先臨時存在char數組中,待會再從char數組中獲取出來.
3):字符串流:StringReader/StringWriter 先將數據(字符串)從程序寫出到stringwriter中,即臨時存儲到字符串中,然後將stringwriter中的內容讀入程序並列印出來。

九、尾聲

IO,對象傳輸的基石(一),完成了。

天天打碼,天天進步!!!


如果覺得本文有用,可以關注+轉發,您的鼓勵就是我創作的最大動力。

相關焦點

  • IO,對象傳輸的基石(二)
    (在網絡上傳輸).;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.io.Serializable;//對象流 ObjectInputpublic class Test { public
  • Netty結合Protostuff傳輸35萬個對象案例
    important}單純netty結合protostuff進行rpc對象傳輸的demo網上有很多,大部分都是一個模子刻出來的,一開始我也是抄了一個,本地測試暢通無阻,未發生任何異常。再看encoder,編碼器,首先將要傳輸的對象用ProtostuffUtils序列化為byte
  • 在程序中如何正確地創建和銷毀軟體應用系統中文件IO流對象實例
    )傳送到接受該數據的消費者(如屏幕、文件或者內存等)的這一過程的抽象。3、JDK系統庫提供有java.io和java.nio兩種不同的系統程序包如下示圖為JDK系統庫幫助文檔中對Java的核心庫java.io包的功能說明局部截圖。
  • IO知識點學習
    1 IO概述IO指數據的傳輸,可以看作是數據的一種流動,按照流的方向,以內存為基準,輸入input和輸出output,流向內存的叫輸入流,流出內存的叫輸出流。2 字節流2.1 一切皆為字節一切數據在存儲時,都是以二進位數字的形式保存,都是一個一個的字節,那麼傳輸也是如此
  • java——io流總概述
    1.什麼是io流io流就是以流的方式進行數據的傳輸,流可以看作是數據內容的一個載體亦或者是一個數據傳輸的管道。當我們上傳或者在網上下載東西的時候數據都是通過流的方式進行傳輸,說白了就是不斷地向流中提取和插入數據。
  • JAVA IO Stream流總結
    我們把這種數據的傳輸,可以看做是一種數據的流動,按照流動的方向,以內存為基準,分為 輸入input 和 輸出 output ,即流向內存是輸入流,流出內存的輸出流。Java中I/O操作主要是指使用 java.io 包下的內容,進行輸入、輸出操作。輸入也叫做讀取數據,輸出也叫做作寫 出數據。一.java.io.File 類1.
  • Java IO流詳解(面試不要再問我IO流)
    ObjectInputStream:對象輸入流,用來提供對「基本數據或對象」的持久存儲。通俗點講,就是能直接傳輸Java對象(序列化、反序列化用)。下面通過一個例子講解InputStream中常用的方法的使用:字節輸出流 OutputStream與字節輸入流類似,java.io 包下所有字節輸出流大多是從抽象類 OutputStream 繼承而來的。
  • Java中IO流的通俗講義
    這樣也就實現了數據的傳輸。在我們一開始提到的FileInputStream類和FileOutputStream類都是節點流,而而節點流外面的緩衝流,它是對一個已存在的流連接和封裝,下面來演示字節緩衝流的使用:import java.io.
  • Java 高性能的異步網絡IO傳輸
    所以,使用異步設計的方法來提升IO性能,我們更需關注如何實現高性能異步網絡傳輸。理想的異步網絡框架程序如果要實現通過網絡傳輸數據,需用到開發語言提供的網絡通信類庫。大部分語言提供的網絡通信基礎類庫都是同步。一個TCP連接建立後,用戶代碼會獲得個收發數據的通道。每個通道會在內存中開闢兩片區域用於收發數據緩存。
  • 實戰 | Netty實現單機壓測秒級接收35萬個對象
    單純netty結合protostuff進行rpc對象傳輸的demo網上有很多,大部分都是一個模子刻出來的,一開始我也是抄了一個,本地測試暢通無阻,未發生任何異常。部署預發環境,進行壓測後,問題巨多,各種報錯層出不窮。
  • Flask-SocketIO 簡單使用指南
    可以從以下三個選項中選擇此程序包所依賴的異步服務:eventlet 性能最佳,支持長輪詢和 WebSocket 傳輸。gevent 在許多不同的配置中得到支持。gevent 包完全支持長輪詢傳輸,但與 eventlet 不同,gevent 沒有本機 WebSocket 支持。
  • 深入java io底層(上)
    1.io流的概念把這些不同類型的輸入、輸出源抽象為流(Stream),其中輸入或輸出的數據稱為數據流(Data Stream),用統一的接口來表示;2.io流的分類按照流向分:,用來提供對「基本數據或對象」的持久存儲。
  • 實戰|Netty+Protostuff實現單機壓測秒級接收35萬個對象
    本文轉載自【微信公眾號:java進階架構師,ID:java_jiagoushi】經微信公眾號授權轉載,如需轉載與原文作者聯繫單純netty結合protostuff進行rpc對象傳輸的demo網上有很多,大部分都是一個模子刻出來的,一開始我也是抄了一個,本地測試暢通無阻,未發生任何異常。
  • Node.JS和Socket.io入門
    現在讓我們開始使用Socket.io首先,我們必須在主伺服器上啟動Socket.io子伺服器。在server.js中:更換:app.listen(port); 為:var io = require('socket.io').listen(app.listen(port));這使Socket.io可以訪問伺服器
  • 使用Netty如何做到單機秒級接收35萬個對象
    單純netty結合protostuff進行rpc對象傳輸的demo網上有很多,大部分都是一個模子刻出來的,一開始我也是抄了一個,本地測試暢通無阻,未發生任何異常。部署預發環境,進行壓測後,問題巨多,各種報錯層出不窮。
  • java中的IO流(字符流和字節流)
    字符編碼有非常多,每個國家都有自己規定的字符編碼,常見的字符編碼有以下幾種:作為中國人,常用的字符編碼有ASCII、 Unicode、UTF-8、GBK(簡、繁體字融於一庫)、GB2312(簡體中文字符集)、BIG5(繁體中文字符集)。
  • JAVA對象的序列化與反序列化
    概述WHAT對象的序列化對象的反序列化PROTOBUFFERWHYHOW使用JDK類庫把對象包裝成JSON字符串總結1. WHAT將對象轉化為字節序列的過程稱為對象的序列化將字節序列恢復為對象的過程稱為對象的反序列化2.
  • Swipe.io超45萬易主,一個被低估的域名後綴.io!
    近日,Swipe.io在park.io上交易成功,價格高達45萬元,這也是截止目前為止.io後綴交易金額最高的域名。該域名於2012年註冊,直譯為「猛擊、偷竊、刷卡、滑動」等。對應諸多國外終端公司,例如,誕生於1962年的美國休斯敦清潔品牌;歐盟國家的電子商務以及支付框架開發商;巴西的區塊鏈網絡公司等等。
  • 實戰 | Netty+Protostuff實現單機壓測秒級接收35萬個對象
    >【034期】JavaEE面試題(六)Hibernate【035期】JavaEE面試題(七)SpringBoot(1)更多內容,點擊上面藍字查看單純netty結合protostuff進行rpc對象傳輸的
  • 阿里雲 E-MapReduce 全面支持 Alluxio
    本文將從三個方面進行介紹:1、什麼是Alluxio2、阿里雲E-MapReduce3、如何在阿里雲E-MapReduce上使用Alluxio什麼是Alluxio?具體說來,Alluxio提供一層文件系統的抽象給計算層。這層抽象之上的計算只需要和Alluxio交互來訪問數據;而這層抽象之下可以同時對接多個不同的持久化存儲(比如一個OSS加上一個HDFS部署),而這層抽象本身又是由部署在靠近計算的內存級Alluxio存儲系統來實現。