天天看點

什麼是IO流?

大家好,我是IT修真院北京分院第27期的JAVA學員,一枚正直純潔善良的java程式員。

今天給大家分享一下,修真院官網Java任務10,深度思考中的知識點———什麼是IO流?

1.背景介紹

什麼是流

流就是一系列的資料

當不同的媒體之間有資料互動的時候,JAVA就使用流來實作。 資料源可以是檔案,還可以是資料庫,網絡甚至是其他的程式。 比如讀取檔案的資料到程式中,站在程式的角度來看,就叫做輸入流。 輸入流: InputStream 輸出流:OutputStream

檔案輸入流

如下代碼,就建立了一個檔案輸入流,這個流可以用來把資料從硬碟的檔案,讀取到JVM(記憶體)。 目前代碼隻是建立了流,還沒有開始讀取。

package stream;
                        
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
                        
public class TestStream {
   public static void main(String[] args) {
     try {
         File f = new File("d:/lol.txt");
          // 建立基于檔案的輸入流
         FileInputStream fis = new FileInputStream(f);
         // 通過這個輸入流,就可以把資料從硬碟,讀取到Java的虛拟機中來,也就是讀取到記憶體中
         } catch (IOException e) {
            // TODO Auto-generated catch block
             e.printStackTrace();
          }
                        
       }
  }
           

--如圖:

什麼是IO流?

标題

2.知識剖析

位元組流

InputStream位元組輸入流 OutputStream位元組輸出流 用于以位元組的形式讀取和寫入資料

ASCII碼 概念

所有的資料存放在計算機中都是以數字的形式存放的。 是以字母就需要轉換為數字才能夠存放。 比如A就對應的數字65,a對應的數字97. 不同的字母和符号對應不同的數字,就是一張碼表。 ASCII是這樣的一種碼表。 隻包含簡單的英文字母,符号,數字等。 不包含中文,德文,俄語等複雜的。

字元 十進制數字 十六進制數字
! 33 21
" 34 22
# 35 23
$ 36 24
% 37 25
& 38 26
' 39 27
( 40 28
) 41 29
* 42 2A
+ 43 2B
, 44 2C
- 45 2D
. 46 2E
/ 47 2F
48 30
1 49 31
2 50 32
3 51 33
4 52 34
5 53 35
6 54 36
7 55 37
8 56 38
9 57 39
: 58 3A
; 59 3B
< 60 3C
= 61 3D
> 62 3E
@ 64 40
A 65 41
B 66 42
C 67 43
D 68 44
E 69 45
F 70 46
G 71 47
H 72 48
I 73 49
J 74 4A
K 75 4B
L 76 4C
M 77 4D
N 78 4E
O 79 4F
P 80 50
Q 81 51
R 82 52
S 83 53
T 84 54
U 85 55
V 86 56
W 87 57
X 88 58
Y 89 59
Z 90 5A
[ 91 5B
\ 92 5C
] 93 5D
^ 94 5E
_ 95 5F
` 96 60
a 97 61
b 98 62
c 99 63
d 100 64
e 101 65
f 102 66
g 103 67
h 104 68
i 105 69
j 106 6A
k 107 6B
l 108 6C
m 109 6D
n 110 6E
o 111 6F
p 112 70
q 113 71
r 114 72
s 115 73
t 116 74
u 117 75
v 118 76
w 119 77
x 120 78
y 121 79
z 122 7A
{ 123 7B
| 124 7C
} 125 7D
~ 126 7E

--

以位元組流的形式讀取檔案内容

InputStream是位元組輸入流,同時也是抽象類,隻提供方法聲明,不提供方法的具體實作。 FileInputStream 是InputStream子類,以FileInputStream 為例進行檔案讀取

以位元組流的形式向檔案寫入資料

OutputStream是位元組輸出流,同時也是抽象類,隻提供方法聲明,不提供方法的具體實作。 FileOutputStream 是OutputStream子類,以FileOutputStream 為例向檔案寫出資料 注: 如果檔案d:/lol2.txt不存在,寫出操作會自動建立該檔案。 但是如果是檔案 d:/xyz/lol2.txt,而目錄xyz又不存在,會抛出異常

資料流

DataInputStream 資料輸入流 DataOutputStream 資料輸出流

直接進行字元串的讀寫

使用資料流的writeUTF()和readUTF() 可以進行資料的格式化順序讀寫 如本例,通過DataOutputStream 向檔案順序寫出 布爾值,整數和字元串。 然後再通過DataInputStream 順序讀入這些資料。 注: 要用DataInputStream 讀取一個檔案,這個檔案必須是由DataOutputStream 寫出的,否則會出現EOFException,因為DataOutputStream 在寫出的時候會做一些特殊标記,隻有DataInputStream 才能成功的讀取。

對象流

對象流指的是可以直接把一個對象以流的形式傳輸給其他的媒體,比如硬碟 一個對象以流的形式進行傳輸,叫做序列化。 該對象所對應的類,必須是實作Serializable接口

序列化一個對象

把一個對象序列化有一個前提是:這個對象的類,必須實作了Serializable接口

字元流

Reader字元輸入流 Writer字元輸出流 專門用于字元的形式讀取和寫入資料

使用字元流讀取檔案

FileReader 是Reader子類,以FileReader 為例進行檔案讀取

使用字元流把字元串寫入到檔案

FileWriter 是Writer的子類,以FileWriter 為例把字元串寫入到檔案

緩存流

以媒體是硬碟為例,位元組流和字元流的弊端: 在每一次讀寫的時候,都會通路硬碟。 如果讀寫的頻率比較高的時候,其性能表現不佳。 為了解決以上弊端,采用緩存流。 緩存流在讀取的時候,會一次性讀較多的資料到緩存中,以後每一次的讀取,都是在緩存中通路,直到緩存中的資料讀取完畢,再到硬碟中讀取。 就好比吃飯,不用緩存就是每吃一口都到鍋裡去鏟。用緩存就是先把飯盛到碗裡,碗裡的吃完了,再到鍋裡去鏟 緩存流在寫入資料的時候,會先把資料寫入到緩存區,直到緩存區達到一定的量,才把這些資料,一起寫入到硬碟中去。按照這種操作模式,就不會像位元組流,字元流那樣每寫一個位元組都通路硬碟,進而減少了IO操作。

使用緩存流讀取資料

緩存字元輸入流 BufferedReader 可以一次讀取一行數

使用緩存流寫出資料

PrintWriter 緩存字元輸出流, 可以一次寫出一行資料

FLUSH方法

有的時候,需要立即把資料寫入到硬碟,而不是等緩存滿了才寫出去。 這時候就需要用到flush

3.常見問題

如何關閉流

所有的流,無論是輸入流還是輸出流,使用完畢之後,都應該關閉。 如果不關閉,會産生對資源占用的浪費。 當量比較大的時候,會影響到業務的正常開展

4.解決方案

  • 在try中關閉

在try的作用域裡關閉檔案輸入流,在前面的示例中都是使用這種方式,這樣做有一個弊端; 如果檔案不存在,或者讀取的時候出現問題而抛出異常,那麼就不會執行這一行關閉流的代碼,存在巨大的資源占用隐患。 不推薦使用

  • 在finally中關閉

這是标準的關閉流的方式 1. 首先把流的引用聲明在try的外面,如果聲明在try裡面,其作用域無法抵達finally. 2. 在finally關閉之前,要先判斷該引用是否為空 3. 關閉的時候,需要再一次進行try catch處理 這是标準的嚴謹的關閉流的方式,但是看上去很繁瑣,是以寫不重要的或者測試代碼的時候,都會采用上面的有隐患try的方式,因為不麻煩

  • 使用try()的方式

把流定義在try()裡,try,catch或者finally結束的時候,會自動關閉 這種編寫代碼的方式叫做 try-with-resources, 這是從JDK7開始支援的技術 所有的流,都實作了一個接口叫做 AutoCloseable,任何類實作了這個接口,都可以在try()中進行執行個體化。 并且在try, catch, finally結束的時候自動關閉,回收相關資源

5.編碼實戰

詳見視訊

https://v.qq.com/x/page/z0767my4wju.html?pcsharecode=VbuMUEue&sf=uri

6.擴充思考

SYSTEM.IN使用

System.out 是常用的在控制台輸出資料的 System.in 可以從控制台輸入資料

使用SYSTEM.IN.READ雖然可以讀取資料,但是很不友善。使用SCANNER就可以逐行讀取了

7.    參考文獻

how2j.cn: http://how2j.cn/k/io/io-system-in/352.html#nowhere

8.    更多讨論

Q1:io流的存儲位置和流向問題?

A1:IO流一般是以記憶體為基準,我們的IO流最開始是在jvm中,然後流向硬碟。

Q2:IO流傳輸時,是以檔案為機關傳輸,還是以檔案内位元組或字元依次傳輸?

A2:兩種情況都有,隻是進行檔案傳輸時候,會産生垃圾資料,锟斤拷

Q3:中文問題?

A3:工作後經常接觸的編碼方式有如下幾種:

ISO-8859-1 ASCII 數字和西歐字母

GBK GB2312 BIG5 中文

UNICODE (統一碼,萬國碼)

其中

ISO-8859-1 包含 ASCII

GB2312 是簡體中文,BIG5是繁體中文,GBK同時包含簡體和繁體以及日文。

UNICODE 包括了所有的文字,無論中文,英文,藏文,法文,世界所有的文字都包含其中

今天的分享就到這裡啦,歡迎大家點贊、轉發、留言、拍磚~

繼續閱讀