IO流

# Java 流式輸入 輸出原理

# Java 流的分類

# 輸入 輸出 流 類

# 常見的節(jié)點流 和 處理流

# 文件流

# 緩沖流

# 數(shù)據(jù)流

# 轉(zhuǎn)換流

# Print流

# Object 流

Java 流式輸入 輸出 原理

在Java程序中 對于數(shù)據(jù)的輸入 輸出操作以 流 stream方式進行,J2SDK 提供了各種各樣的 流 類,用以獲取不同種類的數(shù)據(jù) 程序中通過標準的方法 輸入或輸出數(shù)據(jù)

File封裝的是文件的文件名,真正的文件是硬盤上的一塊空間,文件內(nèi)存著各種數(shù)據(jù),通過流的方式讀取文件內(nèi)的數(shù)據(jù)。對于計算機而言,讀取計算機的文件都是0101,

將文件 模擬成 一個桶? 讀取文件內(nèi)的數(shù)據(jù),可以通過 在桶上安裝一個管道,然后打開水龍頭 開始出水, 這根管道就叫做流,Java里流式的輸入輸出 與水流的原理相同,從文件內(nèi)讀取數(shù)據(jù)時,安插一個管道讀取數(shù)據(jù),寫數(shù)據(jù)時,往文件上插入管道,一直灌水。

這個文件可以是硬盤上或者內(nèi)存里的文件,也可以是網(wǎng)絡(luò)上的數(shù)據(jù),連接對方的某一端口,有的時候 管道內(nèi)的水不是你想要的純凈水 有一些雜質(zhì) 需要過濾,這個時候需要 在外面再包一層管道,就是對0101字節(jié)數(shù)據(jù) 再進行一些封裝,轉(zhuǎn)換成字符串(管道)。流式原理中最重要的就是這些不同的管道。

Java流式輸入輸出原理

輸入 輸出流的分類:

java.io 包中定義了多個流類型(類或抽象類)實現(xiàn)輸入輸出功能,可以從不同角度對其進行分類:

按照數(shù)據(jù)流的方向可以分為:輸入流和輸出流,按照處理數(shù)據(jù)的單位可以分為字節(jié)流和字符流。按照功能不同可以分為節(jié)點流和處理流。

J2SDK所提供的所有流類型位于Java.io內(nèi)都分別繼承自以下四種抽象流類型:


輸入 輸出流的分類

? ? ? ? ? ? ? ? ? ?字節(jié)流 ? ? ? ? ? ? ?字符流(四個抽象流)

輸入流 ? ? ? InputStream ? ? ?Reader

輸出流 ? ? ? OutputStream ? ?Writer

接入文件讀取文件的數(shù)據(jù),針對文件而言是輸出,針對程序而言是輸入,我們是從程序的角度出發(fā)。

字節(jié)流:讀出的數(shù)據(jù)是010101 ?8位一個字節(jié)的讀取。

字符流:一個字符 一個字符 兩個字節(jié)的處理? Java是unicode字符串 ?UTF-16

節(jié)點流和處理流

節(jié)點流:管道直接連接到數(shù)據(jù)源,即可以從一個特定的數(shù)據(jù)源(節(jié)點)讀寫數(shù)據(jù)。(如 文件 內(nèi)存)

處理流:如果對原始的節(jié)點流 處理的不合適 可以在流處理時 ?套入其他管道,即“”“連接”在已存在的流(節(jié)點流或處理流)之上,通過對數(shù)據(jù)的處理為程序員提供更為強大的讀寫功能。 ?水流里有雜質(zhì),一層層過濾 處理,針對數(shù)據(jù)提供更高級的處理,更強大的讀寫功能。

InputStream


字節(jié)流輸入子類圖

繼承自InputStream(抽象類)的流都是用于向程序中輸入數(shù)據(jù),且數(shù)據(jù)的單位為字節(jié)(8bit),深色為節(jié)點流,淺色為處理流。ObjectInputStream ?把對象從字節(jié)流里讀取出來,涉及到對象的序列化。

InputStream的基本方法:


InputStream 基本方法

int read() throws IOException ?// 讀取一個字節(jié)并以整數(shù)形式返回 0-255,如果返回-1就到輸入流的末尾 ?每次讀取一個字節(jié) 每次讀取一個字節(jié)

int read(byte[] buffer) throws IOException // 讀取一系列字節(jié)并存儲到一個數(shù)組Buffer(內(nèi)存中的緩沖區(qū)),返回實際讀取的字節(jié)數(shù),如果讀取前已到輸入流的末尾返回-1 ? 將buffer字節(jié)數(shù)組填滿數(shù)據(jù)之后,再進行處理。 電驢 下載 p2p軟件比較毀硬盤,讀取比較頻繁,容易損傷,不能每次讀取一個字節(jié)訪問一次硬盤。在內(nèi)存里開辟一個空間,讀一次硬盤將該空間(字節(jié)數(shù)組)裝滿,大大減少對硬盤的訪問次數(shù)。寫的時候,將該空間填滿,再一次性寫進硬盤。減少對硬盤的訪問次數(shù)。

int read(byte[] buffer,int offset,int length) throws IOException ?// 讀取length個字節(jié),并存儲到一個字節(jié)數(shù)組buffer 從offset位置開始 返回實際讀取的字節(jié)數(shù) 如果讀取前已到輸入流的末尾返回-1

void close() throws IOException // 關(guān)閉流釋放內(nèi)存資源

long skip(long n) throws IOException // 跳過n個字節(jié)不讀,返回實際跳過的字節(jié)數(shù)

OutputStream:


OutputStream

繼承自O(shè)utputStream的流是用于程序中輸入數(shù)據(jù),且數(shù)據(jù)的單位為字節(jié)(8bit):深色為節(jié)點流、淺色為處理流。

OutputStream的基本方法


OutputStream 基本方法

void write(int b) throws IOException // 向輸出流寫入一個字節(jié)數(shù)據(jù),該字節(jié)數(shù)據(jù)為參數(shù)b的低8位

void write(byte[] b) throws IOException // 將一個字節(jié)類型的數(shù)組中的數(shù)據(jù)寫入輸出流

void write(byte[] b,int off,int len) throws IOException // 將一個字節(jié)類型的數(shù)組從指定位置off 開始的len個字節(jié)寫入到輸出流

void close() throws IOException // 關(guān)閉流釋放內(nèi)存資源

void flush() throws IOException // 將輸出流中緩沖的數(shù)據(jù)全部寫到目的地


close之前需要flush

close 之前調(diào)用flush,close比較粗暴 直接關(guān)閉流釋放了內(nèi)存資源,假如此時緩沖區(qū)尚有部分數(shù)據(jù)為通過“管道”寫入到目的地。

Reader:

繼承自Reader的流都是用于向程序中輸入數(shù)據(jù),且數(shù)據(jù)的單位為字符,兩個字節(jié),16bit,下圖中深色為節(jié)點流,淺色為處理流。

Reader

中文字符在Java 中是兩個字節(jié)的存在,為了保障其能正常顯示,必須一個字符一個字符即兩個字節(jié)兩個字節(jié)的讀取。

Reader的基本方法:


Reader的基本方法

int read() throws IOException? // 讀取一個字符并以整數(shù)形式返回 0-255,如果返回-1就到輸入流的末尾? 每次讀取一個字符?每次讀取一個字符

int read(char[] cbuffer) throws IOException // 讀取一系列字符并存儲到一個數(shù)組Buffer(內(nèi)存中的緩沖區(qū)),返回實際讀取的字符數(shù),如果讀取前已到輸入流的末尾返回-1 ? 將buffer字符數(shù)組填滿數(shù)據(jù)之后,再進行處理。

int read(char[] cbuffer,int offset,int length) throws IOException ?// 讀取length個字符,并存儲到一個字符數(shù)組buffer 從offset位置開始 返回實際讀取的字符數(shù) 如果讀取前已到輸入流的末尾返回-1

void close() throws IOException // 關(guān)閉流釋放內(nèi)存資源

long skip(long n) throws IOException // 跳過n個字節(jié)不讀,返回實際跳過的字符數(shù)

Writer:

繼承自Writer的流都是用于從程序中輸出數(shù)據(jù),且數(shù)據(jù)的單位為字符,兩個字節(jié),16bit,下圖中深色為節(jié)點流,淺色為處理流。


Writer的基本方法

Writer的基本方法

void write(int c) throws IOException // 向輸出流寫入一個字符數(shù)據(jù),該字符數(shù)據(jù)為參數(shù)b的低16位

void write(char[] cbuf) throws IOException // 將一個字符類型的數(shù)組中的數(shù)據(jù)寫入輸出流

void write(char[] cbuf,int off,int len) throws IOException // 將一個字符類型的數(shù)組從指定位置off 開始的len個字符寫入到輸出流

void write(String string) throws IOException // 將一個字符串中的字符寫入輸出流

void write(String string,int off,int len) throws IOException // 將一個字符串從off開始的len個字符寫入到輸出流

void close() throws IOException // 關(guān)閉流釋放內(nèi)存資源

void flush() throws IOException // 將輸出流中緩沖的數(shù)據(jù)全部寫到目的地

節(jié)點流類型:

節(jié)點流

節(jié)點流:直接處理數(shù)據(jù)源數(shù)據(jù)的流類,直接處理文件 內(nèi)存里的數(shù)組 內(nèi)存里的String 以及管道(線程和線程之間通信)


訪問文件

訪問文件:

FileInputStream 和 FileOutputStream 分別繼承自InputStream和OutputStream,用于向文件中輸入或輸出字節(jié)。

FileInputStream和FileOutputStream 常用構(gòu)造方法:

FileInputStream(String name) throws FileNotFoundException

FileInputStream(File file) throws FileNotFoundException

FileOutputStream(String name) throws FileNotFoundException

FileOutputStream(File file) throws FileNotFoundException (無文件會自動創(chuàng)建該文件 只能建文件 不能建目錄)

FileOutputStream(File file,Boolean append) throws FileNotFoundException

FileInputStream和FileOutputStream類支持其父類InputStream和OutputStream所提供的數(shù)據(jù)讀寫方法

注意:在實例化FileInputStream和FileOutputStream實例要try-catch 語句以處理其可能拋出的FileNotFoundException。在讀寫數(shù)據(jù)時也要用try-catch 語句以處理可能拋出的IOException,是其子類。

\\ 是window下在Java程序中定義的路徑分隔符 ?或者 ?/ ? ?正斜杠

以字節(jié)形式讀取字符數(shù)據(jù)的話 ?無法轉(zhuǎn)換成功 ?用Reader讀取 ?也可能是編碼格式問題


處理流:

處理流

處理節(jié)點流或處理流的返回的數(shù)據(jù),相當于對數(shù)據(jù)進行多層封裝。


緩沖流

緩沖流要“”“套接在”相應(yīng)的節(jié)點流上,對讀寫的數(shù)據(jù)提供了緩沖的功能,提高了讀寫的效率,同時增加了一些新的方法。四種緩沖流,常用構(gòu)造:

BufferedReader(Reader in)

BufferedReader(Reader in,int sz) // sz為自定義緩存區(qū)的大小

BufferedWriter(Writer out)

BufferedWriter(Writer out,int sz)

BufferedInputStream(InputStream in)

BufferedInputStream(InputStream in,int sz)

BufferedOutputStream(OutputStream out)

BufferedOutputStream(OutputStream out,int size)

緩沖輸入流支持其父類的mark和reset方法

BufferedReader提供了readLine方法用于讀取一行字符串(以\r或\n分隔)

BufferedWriter提供了newLine用于寫入一個行分隔符

對于輸出的緩沖流,寫出的數(shù)據(jù)會先在內(nèi)存中緩存,使用flush方法將會使內(nèi)存中的數(shù)據(jù)立刻寫出。


處理流與節(jié)點流(字節(jié))的管道封裝


處理流與節(jié)點流(字符)的管道封裝

轉(zhuǎn)換流:

字節(jié)到字符的轉(zhuǎn)換流

字節(jié)流轉(zhuǎn)換為字符流,InputStreamReader和OutputStreamWriter用于字節(jié)數(shù)據(jù)到字符數(shù)據(jù)知己恩的轉(zhuǎn)換。InputStreamReader需要和InutStream進行“”“套接”,OutputStreamWriter需要和OutputStream“套接”,轉(zhuǎn)換流在構(gòu)造時可以指定其編碼集合,比如: InputStream isr = new InputStreamReader(System.in,"ISO8859_1");

中文window默認編碼 gbk


轉(zhuǎn)換流

可以直接寫中文和String,比較好用。


字節(jié)轉(zhuǎn)字符進行緩沖流處理

首先 字節(jié)(阻塞式方法、同步方法 System.in)轉(zhuǎn)字符 然后進行緩沖流處理。

數(shù)據(jù)流

DataInputStream和DataOutputStream分別繼承自InputStream和outputStream,屬于處理流,需要分別套接在InputStream和OutputStream類型的節(jié)點流上。

DataInputStream和DataOutputStream提供了可以存取與機器無關(guān)的原始類型數(shù)據(jù)(int double)等方法

DataInputStream和DataOutputStream的構(gòu)造方法:

DataInputStream(InputStream in)

DataOutputStream(OutputStream in)

網(wǎng)絡(luò)上傳輸數(shù)據(jù)時 ?經(jīng)常使用ReadUTF() ?utf-8 比較省空間 網(wǎng)絡(luò)上用的比較多

數(shù)據(jù)流

直接操作原始數(shù)據(jù)類型的數(shù)據(jù)讀寫,比較方便好用。

先寫的先讀。new DataOutputStream(new ByteArrayOutputStream())

.writeDouble(Math.random()) ?// 內(nèi)存中占8個字節(jié) 可以同DataOutputStream直接寫入

.writeBoolean(true) // 內(nèi)存中占1個字節(jié)

new DataInputStream(new ByteArrayInputStream(baos.toByteArray()))

.readDouble() ?// 先寫的先讀 ?或者容易出現(xiàn)亂碼

.readBoolean()

基本數(shù)據(jù)類型數(shù)據(jù) 的直接寫入 與ByteArrayInutStream的結(jié)合

Print 流 只有輸出流

自動flush,PrintWriter 和 PrintStream 輸出操作不會拋出異常。用戶通過檢測錯誤狀態(tài)獲取錯誤信息。


PrintStream重定向

Object流 -- 序列化(標記型接口 給編譯器看) 外部化 transient 保存和傳遞 對象狀態(tài)


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容