1、Java IO 流
io是java中實現輸入輸出的基礎,它可以很方便的完成數據的輸入輸出操作,Java把不同的輸入輸出抽象為流,通過流的方式允許Java程序使用相同的方式來訪問不同的輸入、輸出。
2、流的分類
輸入流、輸出流 ?
A、輸入流:只能從中讀取數據,而不能向里面寫數據
B、 輸出流:只能向里面寫數據,而不能讀數據
可以這樣理解,數據從內存到硬盤,通常認為是輸出流,即 寫操作 ;相反,從硬盤到內存,通常認為是輸入流,即讀操作;這里的輸入、輸出是 從內存的角度劃分的 。
Java的輸入流主要有InputStream和Reader作為基類,而輸出流則主要由OutputStream和Writer作為基類;
?
字節流和字符流
字節流和字符流區別非常簡單,它們的用法幾乎一樣。區別在于字節流和字符流所操作的數據單元不同:字節流操作的最小單元數據是8位字節,而字符流作為最小數據單元是16為字節。
字節流主要由InputStream、OutputStream作為基類,而字符流則主要由Reader和Writer作為基類完成。
節點流和處理流
按照流的角色分,可以分為節點流和處理流。
可以從、向一個特定的IO設備,讀寫數據流,稱為節點流,節點流常常也被常務低級流(Low Level Stream)
處理流則用于對一個已經存在的流進行連接封裝,通過封裝后來實現數據的讀寫功能。處理流稱為高級流;
當用處理流的進行輸入、輸出時,程序并不會直接連接到實際數據源,沒有和實際的輸入、輸出節點連接。使用處理流一個明顯的好處是:只要使用相同的處理流,程序就可以采用相同的輸入、輸出代碼來訪問不同數據源,隨著處理流鎖包裝節點流的改變,程序實際所訪問的數據源也相應發生改變。
處理流的功能主要體現在兩個方面:
性能提高:主要以增加緩沖方式來提高輸入、輸出的效率
操作的便捷: 處理流可能提供了系列便捷的方法來一次性輸入、輸出大批量的內容,而不是輸入、輸出一個或多個單位數據
處理流可以“嫁接”在任何已經存在的流的基礎上,這就允許Java應用程序采用相同的代碼、透明的方式來訪問不同的輸入、輸出設備輸入流。
字節輸入流 InputStream 和字符輸入流 Reader
InputStream和Reader是所有輸入流的基類,他們都是2個抽象類,本身并不能創建實例來執行輸入,但他們有輸入流的模版,所以它們的方法是所有的輸入流和輸出流可以用的方法。
在InputStream里常用的方法:
int read(): 從輸入流中讀取單個自己
int read(byte[] b): 從輸入流中讀取最多b.length個字節,將讀取的字節存在數組b中,返回實際讀取的字節數
int read(byte[] b, int off, int len): 從輸入流中讀取最多len個字節數據,并將其存儲在數字b中,放入b數組中時,并不是從數組起點開始,而是從off位置開始,返回實際讀取字節數。
在Reader里經常使用的方法:
int read(): 從輸入流中讀取單個字符
int read(char[] c): 從輸入流讀取最多c.length個字符數據,并將其存儲在字符數組c中,返回實際讀取的字符
int read(char[] c, int off, int len): 從輸入流中讀取最多len個字符的數據,將讀取的數據放到字符數組c中保存,從數組的off開始讀取;
InputStream、Reader還支持如下幾個方法移動指針:
void mark(int readAheadLimit): 在記錄指針當前位置第一個標記(mark)
boolean markSupported(): 判斷此輸入流是否支持mark()操作,即是否支持記錄標記
void reset():將此流的記錄的指針重新定位到上一次記錄的標記的位置
long skip(long n):記錄指針向前移動n個字節、字符
OutputStream 字節輸出流和 Writer 字符輸出流
具有以下方法:
void write(int c): 指定的字節、字符輸出到輸出流中
void write(byte[]/char[] buf): 將字節數組/字符數組中的數據傳輸到指定輸出流中
void write(byte[]/char[] buf, int off,int len):將指定數組中的數據輸出到指定輸出流中
字符輸出流還有以下方法:
void write(String s):將指定字符串輸出到指定輸出流中
void write(String s, int off, int len):將字節數組、字符數組中從off位置開始,長度為len的字節、字符輸出到輸出流中
3、Java的輸入、輸出流:
分類 |
字節輸入流 |
字節輸出流 |
字符輸入流 |
字符輸出流 |
抽象基類 |
InputStream |
OutputStream |
Reader |
Writer |
訪問文件 |
FileInputStream |
FileOutputStream |
FileReader |
FileWriter |
訪問數組 |
ByteArrayInputStream |
ByteArrayOutputStream |
CharArrayReader |
CharArrayWriter |
訪問管道 |
PipedInputStream |
PipedOutputStream |
PipedReader |
PipedWriter |
訪問字符串 |
? | ? |
StringReader |
StringWriter |
緩沖流 |
BufferedInputStream |
BufferedOutputStream |
BufferedReader |
BufferedWriter |
轉換流 |
? | ? |
InputStreamReader |
OutputStreamWriter |
對象流 |
ObjectInputStream |
ObjectOutputStream |
? | ? |
抽象基類 |
FilterInputStream |
FilterOutputStream |
FilterReader |
FilterWriter |
打印流 |
? |
PrintStream |
? |
PrintWriter |
推回輸入流 |
PushbackInputStream |
? |
PushbackReader |
? |
特殊流 |
DataInputStream |
DataOutputStream |
? | ? |
輸入、輸出流的體系:
推回輸入流:
有2個特殊流與眾不同,就是PushbackInputStream、PushbackReader,它們有以下常用方法:
void unread(byte[]/char[] buf):將一個字節/字符數組推到緩沖區里,運行重復讀取推回的內容
void unread(byte[]/char[] buf, int off, int len):將一個字節/字符數組從off位置開始讀取,長度是len的字符/字節數組的內容推回到緩沖區中,允許重復剛才讀取的內容
void unread(int b):將一個字節、字符推回到緩沖區
這2個推回輸入流都帶一個緩沖區,當程序調用unread的時候,系統就會把指定數組的內容推回到緩沖區,而推回輸入流每次調用read的方法,總會先去讀取推回緩沖區中的內容,只有完全讀取的緩沖區里面的內容后,而且還沒有裝滿read所需的數組,才會到原輸入流中讀取內容;
重定向標準輸入輸出
在System中有3大標準輸入、輸出方法:
static void setErr(PrintStream e):重定向“標準”錯誤輸出流
static void setIn(InputStream in):重定向“標準”輸入流
static void setOut(OutputStream out):重定向“標準”輸出流
JVM 寫其他進程數據
Runtime對象有exec方法,他可以運行jvm命令行,該方法產生一個Process對象,Process對象代表由該Java程序啟動的子進程,Process類有以下方法,可以和子進程通信;
InputStream getErrorStream():獲取子進程的錯誤流
InputStream getInputStream():獲取子進程的輸入流
OutputStream getOutputStream():獲取子進程的輸入流
4、RandomAccessFile
RandomAccessFile是Java輸入、輸出體系中功能最豐富的文件內容訪問類,它提供了眾多方法來訪問文件內容,它既可以讀文件內容也可以像文件輸出數據。它和普通的輸入、輸出流不同的是,它可以隨機訪問的方式,操作文件數據。
RandomAccessFile可以自由定位文件指針,所以RandomAccessFile可以不從開始的地方輸出,RandomAccessFile可以向已經存在的文件后追加內容。
RandomAccessFile對象包含一個指針用來記錄當前讀寫的位置,當程序新創建一個RandomAccessFile對象時,該指針位于文件頭部,既0的位置;當讀取或寫入了n個字節后,文件指針就指向最后的位置,除此之外,文件指針也是可以隨意移動的,RandomAccessFile有以下方法操作指針:
long getFilePointer():返回文件記錄指針的當前位置
void seek(long pos):將文件記錄指針定位到pos位置
RandomAccessFile既可以讀也可以寫,所以它包含了完全類似于InputStream的read方法,和OutputStream的write方法,用法和原來的都一樣;而且RandomAccessFile還包含了readXxx、writeXxx的輸入輸出方法;
RandomAccessFile的文件訪問模式:
r:以只讀方式打開指定文件
rw:以讀取、寫入方式打開指定文件,如果文件不存在就創建
rws:以讀取、寫入的方式打開指定文件,相對應rw模式,還要求文件內容和元數據的每個更新都同步寫入到底層存儲設備
rwd:以讀取、寫入方式打開指定文件,對于rw,還要求文件內容的每個更新都同步寫入到底層設備
5、序列化
在遠程調用、分布式開發中常用到序列化,將java對象序列化的文件中保存,然后在解析的時候又反序列化,其中需要用到Serializable接口;在實現了該接口的對象可以順利序列化成一個文件保存在硬盤上,反序列化也是通過該接口的id來查找該對象的。
transient可以忽略對象中某個屬性不被序列化。
6 新 NIO
nio常用的包介紹:
java.io 包:主要提供了一些和Buffer相關的類
java.io.channels:包括Selector和Channel的相關類
java.nio.charset:包含和字符集相關的類
java.nio.channels.spi:提供Channel服務類
java.nio.charset.spi:提供文字集的服務類
Buffer介紹
Buffer是提取數據的容器,這里有ByteBuffer、CharBuffer、ShortBuffer、IntBuffer、LongBuffer、FloatBuffer、DoubleBuffer。
上面這些類,除了ByteBuffer之外,都采用類似的方法管理數據,只是各自管理的數據類型不同而已。這些Buffer都沒有構造器,通過使用如下方法來得到一個Buffer對象:
static XxxBuffer allocate(int capacity) 創建一個容量為capacity的XxxBuffer對象
ByteBuffer的子類MappedByteBuffer,它用于表示Chanael將硬盤文件的的部分或全部內容映射到內存中后得到結果,通常MappedByteBuffer對象由Chanael的map方法返回。
在Buffer中有三個重要的概念:容量(capacity)、界限(limit)、位置(position)
容量(capacity):緩沖區的容量(capacity)表示該Buffer的最大數據容量,即最多可以存儲多少數據,緩沖區的容量不能為負數,在創建后是不能改變的。
界限(limit):第一個不應該被讀出或寫入的緩沖區位置索引。也就是說,位于limit后的數據既不能讀,也不能寫。
位置(position):用于指明下一個可以讀出的后者寫入的緩沖區位置索引。類似于IO流中的記錄指針位置。當剛剛新建一個Buffer對象時,容器position為0,如果從Channel讀取了2個數據到該Buffer中,則postion為2,指向Buffer中的第三個。
Buffer常用方法:
int capacity():返回Buffer的capacity的大小
boolean hasRemaining():判斷當前位置(position)和界限(limit)之間是否還有元素可以提供處理。
int limit:返回Buffer的界限(limit)的位置
Buffer limit(int newLimit)重新設置界限的值,并返回一個具有新的limit的緩沖區的對象
Buffer mark():設置Buffer的mark位置,它只能在0和位置position之間做mark
int position():返回當前Buffer的position
Buffer postion(int newPostion):設置Buffer的新位置,并返回一個具有新的limit的緩沖區對象。
int remaining():返回當前位置和界限之間的元素個數
Buffer reset():將position位置設置到mark的位置
Buffer rewind():將位置(position)設置為0,取消設置的mark
當使用put和get來訪問Buffer中的數據時,分為絕對和相對的2種:
相對的Relative:從Buffer中的當前位置讀取和寫入數據,然后將位置(position)的值按處理元素的個數相加。
絕對Absolute:直接根據索引來向Buffer中讀取或寫入數據,使用絕對方式來訪問Buffer理的數據,并不會影響位置position的值。
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
