Java總結IO篇之位元組流與字元流轉化
本篇接上篇:Java中的字元流,流的讀寫的細節參考上篇
本篇講述位元組流相關話題,包括位元組流的讀取與寫出,位元組流轉化為字元流
1.明確是否是純文字: 純文字 ? 字元流: 位元組流
2.明確 資料來源
( 輸入流 I )和 資料流向
( 輸出流 O )
3.I流和O流對接,資料傳輸
另外:需要字元編碼轉換,使用位元組流轉換字元流
資料來源( 輸入流 I ):記憶體、磁碟、網路、鍵盤 資料流向( 輸出流 O ): 記憶體、磁碟、網路、控制檯
1.最常見的幾種流

最常見的幾種流.png
2.流與流之間的相互作用:轉換與包裝

轉換流和包裝流.png
一、FileOutputStream與FileInputStream
1.FileOutputStream:輸出流,寫出操作
FileOutputStream fos = null; try { String fileName = "I:\\Java\\Base\\Thinking\\src\\IOTest\\FileInputStream.txt"; fos = new FileOutputStream(fileName); fos.write("Line1 第一行".getBytes());//不需要重新整理緩衝 } catch (IOException e) { e.printStackTrace(); } finally { try { if (fos != null) { fos.close(); } } catch (IOException e) { e.printStackTrace(); } }

位元組輸出流.png
2.FileInputStream:輸入流,讀進操作
public static void main(String[] args) { try { String fileName = "I:\\Java\\Base\\Thinking\\src\\IOTest\\FileInputStream.txt"; FileInputStream fis = new FileInputStream(fileName); //readOneByOne(fis); //readByByteArrayByWhile(fis); } catch (IOException e) { e.printStackTrace(); } }
1)一個一個 位元組
讀
private static void readOneByOne(FileInputStream fis) throws IOException { int ch = 0; while ((ch = fis.read()) != -1) { System.out.println(ch + "=" + (char) ch); } }
一共輸出了15個位元組,和 Line1 第一行
有出入,原因:
在utf-8編碼下,一箇中文字元佔三個位元組
76=L105=i110=n101=e49=132=231=ç172=¬172=¬228=ä184=¸128=�232=è161=¡140=�
2)位元組陣列方式:
private static void readByByteArrayByWhile(FileInputStream fis) throws IOException { //字元陣列迴圈讀取 byte[] buf = new byte[8]; int len = 0; while ((len = fis.read(buf)) != -1) { System.out.println(new String(buf, 0, len)); } }
可見buf一次裝個位元組, 第
由三個位元組表示,被分成了兩半,所以讀出了亂碼
//Line1 � //�一行
檔案位元組數 System.out.println(fis.available());//15
二、使用位元組流拷貝
視訊大小:576M
1.使用FileInputStream和FileInputStream拷貝
耗時:6.162444569秒
private static void copy() { FileOutputStream fos = null; FileInputStream fis = null; try { fis = new FileInputStream("I:\\Java\\Base\\Thinking\\src\\IOTest\\video.avi"); fos = new FileOutputStream("F:\\javaTest\\IO\\video.avi"); byte[] buf = new byte[1024]; int len = 0; while ((len = fis.read(buf)) != -1) { fos.write(buf, 0, len); } } catch (Exception e) { e.printStackTrace(); } finally { try { if (fis != null) { fis.close(); } } catch (IOException e) { e.printStackTrace(); } try { if (fos != null) { fos.close(); } } catch (IOException e) { e.printStackTrace(); } }
2.使用包裝類BufferedOutputStream和BufferedInputStream拷貝:
方法耗時:33.478968503秒
private static void copyByBuf() { BufferedOutputStream bfos = null; BufferedInputStream bfis = null; try { FileInputStream fis = new FileInputStream("I:\\Java\\Base\\Thinking\\src\\IOTest\\video.avi"); bfis = new BufferedInputStream(fis); FileOutputStream fos = new FileOutputStream("F:\\javaTest\\IO\\video.avi"); bfos = new BufferedOutputStream(fos); int b = 0; while ((b = bfis.read()) != -1) { bfos.write(b); } } catch (Exception e) { e.printStackTrace(); } finally { try { if (bfis != null) { bfis.close(); } } catch (IOException e) { e.printStackTrace(); } try { if (bfos != null) { bfos.close(); } } catch (IOException e) { e.printStackTrace(); } } }
三、位元組流轉化為字元流
場景一:將鍵盤錄入寫入到本地磁碟
分析:鍵盤錄入是一個位元組輸入流: InputStream in = System.in; 由於輸入的都是字元,使用字元流將比較方便(當然位元組流也可以,不過麻煩一點) 1.用字元流InputStreamReader將位元組流轉化 2.再用字元包裝流BufferedReader包裝一下(當然也可以不包裝,不過麻煩一點)

轉換流和包裝流.png
public class Save2File { public static void main(String[] args) throws Exception { //資料來源----鍵盤錄入位元組流轉化為字元流後包裝成BufferedReader BufferedReader bfr = new BufferedReader(new InputStreamReader(System.in)); String path = "I:\\Java\\Base\\Thinking\\src\\IOTest\\鍵盤錄入"; //資料流向 :"I:\\Java\\Base\\Thinking\\src\\IOTest\\鍵盤錄入" 檔案 BufferedWriter brw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path))); String line = null; while ((line=bfr.readLine())!=null){ if ("over".equals(line)) { break; } brw.write(line); brw.newLine(); brw.flush(); } bfr.close(); brw.close(); } }

鍵盤錄入到檔案.png
場景二:將鍵盤錄入寫入到本地磁碟:指定字元編碼
預設字元編碼為utf-8,這裡使用GBK測試
public class Save2File { public static void main(String[] args) throws Exception { //資料來源----鍵盤錄入位元組流轉化為字元流後包裝成BufferedReader BufferedReader bfr = new BufferedReader(new InputStreamReader(System.in)); String path = "I:\\Java\\Base\\Thinking\\src\\IOTest\\鍵盤錄入-GKB"; //資料流向 :"I:\\Java\\Base\\Thinking\\src\\IOTest\\鍵盤錄入" 檔案 BufferedWriter brw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path),"GBK")); String line = null; while ((line=bfr.readLine())!=null){ if ("over".equals(line)) { break; } brw.write(line); brw.newLine(); brw.flush(); } bfr.close(); brw.close(); } }

GBK儲存.png
可見兩者的位元組數不同,一個GBK的漢字佔2個位元組 (2*5+\r\n=12)
,一個UTF-8漢字佔3個位元組 (3*5+\r\n=17)
場景3:讀取檔案輸出到控制檯
分析:控制檯輸出是一個位元組輸出流:PrintStream out = System.out; 由於輸出的都是字元,使用字元流將比較方便(當然位元組流也可以,不過麻煩一點) 1.用字元流OutputStreamWriter將位元組流轉化 2.再用字元包裝流BufferedWriter包裝一下(當然也可以不包裝,不過麻煩一點)
public class ReadFile2Console { public static void main(String[] args) throws Exception { //資料來源----本地檔案 String path = "I:\\Java\\Base\\Thinking\\src\\IOTest\\Activity.md"; BufferedReader bfr = new BufferedReader(new InputStreamReader(new FileInputStream(path))); //資料流向 :"I:\\Java\\Base\\Thinking\\src\\IOTest\\鍵盤錄入" 檔案 BufferedWriter brw = new BufferedWriter(new OutputStreamWriter(System.out)); String line = null; while ((line = bfr.readLine()) != null) { if ("over".equals(line)) { break; } brw.write(line); brw.newLine(); brw.flush(); } bfr.close(); brw.close(); } }

檔案輸出到控制檯.png
場景4:改變系統流的流向
可以改變系統的錄入流(資料來源),和控制檯輸出流(資料流向)
System.setIn(InputStream 輸入流); 自定義System.in資料來源(預設鍵盤錄入) System.setOut(PrintStream 輸出流);自定義System.out資料流向(預設控制檯)
public class ReadFile2Console { public static void main(String[] args) throws Exception { //資料來源----本地檔案 String path = "I:\\Java\\Base\\Thinking\\src\\IOTest\\Activity.md"; System.setIn(new FileInputStream(path));//將鍵盤源改為了磁碟檔案源 System.setOut(new PrintStream("F:\\hell.txt"));//將流向控制檯改為流向磁碟檔案 BufferedReader bfr = new BufferedReader(new InputStreamReader(System.in)); //資料流向 :"I:\\Java\\Base\\Thinking\\src\\IOTest\\鍵盤錄入" 檔案 BufferedWriter brw = new BufferedWriter(new OutputStreamWriter(System.out)); String line = null; while ((line = bfr.readLine()) != null) { if ("over".equals(line)) { break; } brw.write(line); brw.newLine(); brw.flush(); } bfr.close(); brw.close(); } }
後記:捷文規範
1.本文成長記錄及勘誤表
專案原始碼 | 日期 | 備註 |
---|---|---|
V0.1--無 | 2018-10-10 | ofollow,noindex">Java中的位元組流與字元流轉化 |
V0.2--無 | - | - |
2.更多關於我
筆名 | 微信 | 愛好 | |
---|---|---|---|
張風捷特烈 | 1981462002 | zdl1994328 | 語言 |
我的github | 我的簡書 | 我的CSDN | 個人網站 |
3.宣告
1----本文由張風捷特烈原創,轉載請註明
2----歡迎廣大程式設計愛好者共同交流
3----個人能力有限,如有不正之處歡迎大家批評指證,必定虛心改正
4----看到這裡,我在此感謝你的喜歡與支援