# Java 流式輸入 輸出原理
# Java 流的分類
# 輸入 輸出 流 類
# 常見的節(jié)點(diǎn)流 和 處理流
# 文件流
# 緩沖流
# 數(shù)據(jù)流
# 轉(zhuǎn)換流
# Print流
# Object 流
Java 流式輸入 輸出 原理
在Java程序中 對于數(shù)據(jù)的輸入 輸出操作以 流 stream方式進(jìn)行,J2SDK 提供了各種各樣的 流 類,用以獲取不同種類的數(shù)據(jù) 程序中通過標(biāo)準(zhǔn)的方法 輸入或輸出數(shù)據(jù)
File封裝的是文件的文件名箱叁,真正的文件是硬盤上的一塊空間,文件內(nèi)存著各種數(shù)據(jù),通過流的方式讀取文件內(nèi)的數(shù)據(jù)开泽。對于計算機(jī)而言,讀取計算機(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ù) 再進(jìn)行一些封裝挺举,轉(zhuǎn)換成字符串(管道)杀赢。流式原理中最重要的就是這些不同的管道。
輸入 輸出流的分類:
java.io 包中定義了多個流類型(類或抽象類)實(shí)現(xiàn)輸入輸出功能豹悬,可以從不同角度對其進(jìn)行分類:
按照數(shù)據(jù)流的方向可以分為:輸入流和輸出流葵陵,按照處理數(shù)據(jù)的單位可以分為字節(jié)流和字符流液荸。按照功能不同可以分為節(jié)點(diǎn)流和處理流瞻佛。
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é)點(diǎn)流和處理流
節(jié)點(diǎn)流:管道直接連接到數(shù)據(jù)源适刀,即可以從一個特定的數(shù)據(jù)源(節(jié)點(diǎn))讀寫數(shù)據(jù)。(如 文件 內(nèi)存)
處理流:如果對原始的節(jié)點(diǎn)流 處理的不合適 可以在流處理時 ?套入其他管道煤蹭,即“”“連接”在已存在的流(節(jié)點(diǎn)流或處理流)之上笔喉,通過對數(shù)據(jù)的處理為程序員提供更為強(qiáng)大的讀寫功能。 ?水流里有雜質(zhì)硝皂,一層層過濾 處理常挚,針對數(shù)據(jù)提供更高級的處理,更強(qiáng)大的讀寫功能稽物。
InputStream
繼承自InputStream(抽象類)的流都是用于向程序中輸入數(shù)據(jù)奄毡,且數(shù)據(jù)的單位為字節(jié)(8bit),深色為節(jié)點(diǎn)流贝或,淺色為處理流吼过。ObjectInputStream ?把對象從字節(jié)流里讀取出來,涉及到對象的序列化咪奖。
InputStream的基本方法:
int read() throws IOException ?// 讀取一個字節(jié)并以整數(shù)形式返回 0-255盗忱,如果返回-1就到輸入流的末尾 ?每次讀取一個字節(jié) 每次讀取一個字節(jié)
int read(byte[] buffer) throws IOException // 讀取一系列字節(jié)并存儲到一個數(shù)組Buffer(內(nèi)存中的緩沖區(qū)),返回實(shí)際讀取的字節(jié)數(shù)羊赵,如果讀取前已到輸入流的末尾返回-1 ? 將buffer字節(jié)數(shù)組填滿數(shù)據(jù)之后趟佃,再進(jìn)行處理。 電驢 下載 p2p軟件比較毀硬盤,讀取比較頻繁揖闸,容易損傷揍堕,不能每次讀取一個字節(jié)訪問一次硬盤。在內(nèi)存里開辟一個空間汤纸,讀一次硬盤將該空間(字節(jié)數(shù)組)裝滿衩茸,大大減少對硬盤的訪問次數(shù)。寫的時候贮泞,將該空間填滿楞慈,再一次性寫進(jìn)硬盤。減少對硬盤的訪問次數(shù)啃擦。
int read(byte[] buffer,int offset,int length) throws IOException ?// 讀取length個字節(jié)囊蓝,并存儲到一個字節(jié)數(shù)組buffer 從offset位置開始 返回實(shí)際讀取的字節(jié)數(shù) 如果讀取前已到輸入流的末尾返回-1
void close() throws IOException // 關(guān)閉流釋放內(nèi)存資源
long skip(long n) throws IOException // 跳過n個字節(jié)不讀,返回實(shí)際跳過的字節(jié)數(shù)
OutputStream:
繼承自O(shè)utputStream的流是用于程序中輸入數(shù)據(jù)令蛉,且數(shù)據(jù)的單位為字節(jié)(8bit):深色為節(jié)點(diǎn)流聚霜、淺色為處理流。
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 之前調(diào)用flush蝎宇,close比較粗暴 直接關(guān)閉流釋放了內(nèi)存資源,假如此時緩沖區(qū)尚有部分?jǐn)?shù)據(jù)為通過“管道”寫入到目的地祷安。
Reader:
繼承自Reader的流都是用于向程序中輸入數(shù)據(jù)姥芥,且數(shù)據(jù)的單位為字符,兩個字節(jié)汇鞭,16bit凉唐,下圖中深色為節(jié)點(diǎn)流,淺色為處理流霍骄。
中文字符在Java 中是兩個字節(jié)的存在台囱,為了保障其能正常顯示,必須一個字符一個字符即兩個字節(jié)兩個字節(jié)的讀取腕巡。
Reader的基本方法:
int read() throws IOException? // 讀取一個字符并以整數(shù)形式返回 0-255玄坦,如果返回-1就到輸入流的末尾? 每次讀取一個字符?每次讀取一個字符
int read(char[] cbuffer) throws IOException // 讀取一系列字符并存儲到一個數(shù)組Buffer(內(nèi)存中的緩沖區(qū)),返回實(shí)際讀取的字符數(shù)绘沉,如果讀取前已到輸入流的末尾返回-1 ? 將buffer字符數(shù)組填滿數(shù)據(jù)之后煎楣,再進(jìn)行處理。
int read(char[] cbuffer,int offset,int length) throws IOException ?// 讀取length個字符车伞,并存儲到一個字符數(shù)組buffer 從offset位置開始 返回實(shí)際讀取的字符數(shù) 如果讀取前已到輸入流的末尾返回-1
void close() throws IOException // 關(guān)閉流釋放內(nèi)存資源
long skip(long n) throws IOException // 跳過n個字節(jié)不讀择懂,返回實(shí)際跳過的字符數(shù)
Writer:
繼承自Writer的流都是用于從程序中輸出數(shù)據(jù),且數(shù)據(jù)的單位為字符另玖,兩個字節(jié)困曙,16bit表伦,下圖中深色為節(jié)點(diǎn)流,淺色為處理流慷丽。
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é)點(diǎn)流類型:
節(jié)點(diǎn)流:直接處理數(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ù)讀寫方法
注意:在實(shí)例化FileInputStream和FileOutputStream實(shí)例要try-catch 語句以處理其可能拋出的FileNotFoundException纲熏。在讀寫數(shù)據(jù)時也要用try-catch 語句以處理可能拋出的IOException,是其子類锄俄。
\\ 是window下在Java程序中定義的路徑分隔符 ?或者 ?/ ? ?正斜杠
以字節(jié)形式讀取字符數(shù)據(jù)的話 ?無法轉(zhuǎn)換成功 ?用Reader讀取 ?也可能是編碼格式問題
處理流:
處理節(jié)點(diǎn)流或處理流的返回的數(shù)據(jù)局劲,相當(dāng)于對數(shù)據(jù)進(jìn)行多層封裝。
緩沖流要“”“套接在”相應(yīng)的節(jié)點(diǎn)流上奶赠,對讀寫的數(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ù)立刻寫出谈跛。
轉(zhuǎn)換流:
字節(jié)流轉(zhuǎn)換為字符流羊苟,InputStreamReader和OutputStreamWriter用于字節(jié)數(shù)據(jù)到字符數(shù)據(jù)知己恩的轉(zhuǎn)換塑陵。InputStreamReader需要和InutStream進(jìn)行“”“套接”,OutputStreamWriter需要和OutputStream“套接”蜡励,轉(zhuǎn)換流在構(gòu)造時可以指定其編碼集合令花,比如: InputStream isr = new InputStreamReader(System.in,"ISO8859_1");
中文window默認(rèn)編碼 gbk
可以直接寫中文和String,比較好用凉倚。
首先 字節(jié)(阻塞式方法兼都、同步方法 System.in)轉(zhuǎn)字符 然后進(jìn)行緩沖流處理。
數(shù)據(jù)流
DataInputStream和DataOutputStream分別繼承自InputStream和outputStream,屬于處理流稽寒,需要分別套接在InputStream和OutputStream類型的節(jié)點(diǎn)流上扮碧。
DataInputStream和DataOutputStream提供了可以存取與機(jī)器無關(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ù)讀寫,比較方便好用杏糙。
先寫的先讀慎王。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()
Print 流 只有輸出流
自動flush,PrintWriter 和 PrintStream 輸出操作不會拋出異常宏侍。用戶通過檢測錯誤狀態(tài)獲取錯誤信息赖淤。
Object流 -- 序列化(標(biāo)記型接口 給編譯器看) 外部化 transient 保存和傳遞 對象狀態(tài)