NIO API
主要集中在
java.nio
和它的
subpackages
中:
?
java.nio
定義了
Buffer
及其數(shù)據(jù)類型相關的子類。其中被
java.nio.channels
中的類用來進行
IO
操作的
ByteBuffer
的作用非常重要。
?
java.nio.channels
定義了一系列處理
IO
的
Channel
接口以及這些接口在文件系統(tǒng)和網(wǎng)絡通訊上的實現(xiàn)。通過
Selector
這個類,還提供了進行非阻塞
IO
操作的辦法。這個包可以說是
NIO API
的核心。
?
java.nio.channels.spi
定義了可用來實現(xiàn)
channel
和
selector API
的抽象類。
?
java.nio.charset
??????
定義了處理字符編碼和解碼的類。
?
java.nio.charset.spi
??????
定義了可用來實現(xiàn)
charset API
的抽象類。
?
java.nio.channels.spi
和
java.nio.charset.spi
這兩個包主要被用來對現(xiàn)有
NIO API
進行擴展,在實際的使用中,我們一般只和另外的
3
個包打交道。下面將對這
3
個包一一介紹。
?
Package java.nio
這個包主要定義了
Buffer
及其子類。
Buffer
定義了一個線性存放
primitive type
數(shù)據(jù)的容器接口。對于除
boolean
以外的其他
primitive type
,都有一個相應的
Buffer
子類,
ByteBuffer
是其中最重要的一個子類。
?
下面這張
UML
類圖描述了
java.nio
中的類的關系:
?
Buffer
定義了一個可以線性存放
primitive type
數(shù)據(jù)的容器接口。
Buffer
主要包含了與類型(
byte, char…
)無關的功能。值得注意的是
Buffer
及其子類都不是線程安全的。
?
每個
Buffer
都有以下的屬性:
?
capacity
這個
Buffer
最多能放多少數(shù)據(jù)。
capacity
一般在
buffer
被創(chuàng)建的時候指定。
limit
在
Buffer
上進行的讀寫操作都不能越過這個下標。當寫數(shù)據(jù)到
buffer
中時,
limit
一般和
capacity
相等,當讀數(shù)據(jù)時,
limit
代表
buffer
中有效數(shù)據(jù)的長度。
position
讀
/
寫操作的當前下標。當使用
buffer
的相對位置進行讀
/
寫操作時,讀
/
寫會從這個下標進行,并在操作完成后,
buffer
會更新下標的值。
mark
一個臨時存放的位置下標。調用
mark()
會將
mark
設為當前的
position
的值,以后調用
reset()
會將
position
屬性設置為
mark
的值。
mark
的值總是小于等于
position
的值,如果將
position
的值設的比
mark
小,當前的
mark
值會被拋棄掉。
?
這些屬性總是滿足以下條件:
0 <= mark <= position <= limit <= capacity
?
limit
和
position
的值除了通過
limit()
和
position()
函數(shù)來設置,也可以通過下面這些函數(shù)來改變:
?
Buffer clear()
把
position
設為
0
,把
limit
設為
capacity
,一般在把數(shù)據(jù)寫入
Buffer
前調用。
Buffer flip()
把
limit
設為當前
position
,把
position
設為
0
,一般在從
Buffer
讀出數(shù)據(jù)前調用。
Buffer rewind()
把
position
設為
0
,
limit
不變,一般在把數(shù)據(jù)重寫入
Buffer
前調用。
?
Buffer
對象有可能是只讀的,這時,任何對該對象的寫操作都會觸發(fā)一個
ReadOnlyBufferException
。
isReadOnly()
方法可以用來判斷一個
Buffer
是否只讀。
?
ByteBuffer
在
Buffer
的子類中,
ByteBuffer
是一個地位較為特殊的類,因為在
java.io.channels
中定義的各種
channel
的
IO
操作基本上都是圍繞
ByteBuffer
展開的。
?
ByteBuffer
定義了
4
個
static
方法來做創(chuàng)建工作:
?
ByteBuffer allocate(int capacity)
創(chuàng)建一個指定
capacity
的
ByteBuffer
。
ByteBuffer allocateDirect(int capacity)
創(chuàng)建一個
direct
的
ByteBuffer
,這樣的
ByteBuffer
在參與
IO
操作時性能會更好(很有可能是在底層的實現(xiàn)使用了
DMA
技術),相應的,創(chuàng)建和回收
direct
的
ByteBuffer
的代價也會高一些。
isDirect()
方法可以檢查一個
buffer
是否是
direct
的。
ByteBuffer wrap(byte [] array)
ByteBuffer wrap(byte [] array, int offset, int length)
把一個
byte
數(shù)組或
byte
數(shù)組的一部分包裝成
ByteBuffer
。
?
ByteBuffer
定義了一系列
get
和
put
操作來從中讀寫
byte
數(shù)據(jù),如下面幾個:
?
byte get()
ByteBuffer get(byte [] dst)
byte get(int index)
?
ByteBuffer put(byte b)
ByteBuffer put(byte [] src)
ByteBuffer put(int index, byte b)
?
這些操作可分為絕對定位和相對定為兩種,相對定位的讀寫操作依靠
position
來定位
Buffer
中的位置,并在操作完成后會更新
position
的值。
在其它類型的
buffer
中,也定義了相同的函數(shù)來讀寫數(shù)據(jù),唯一不同的就是一些參數(shù)和返回值的類型。
?
除了讀寫
byte
類型數(shù)據(jù)的函數(shù),
ByteBuffer
的一個特別之處是它還定義了讀寫其它
primitive
數(shù)據(jù)的方法,如:
?
int getInt()
??????
從
ByteBuffer
中讀出一個
int
值。
ByteBuffer putInt(int value)
??????
寫入一個
int
值到
ByteBuffer
中。
?
讀寫其它類型的數(shù)據(jù)牽涉到字節(jié)序問題,
ByteBuffer
會按其字節(jié)序(大字節(jié)序或小字節(jié)序)寫入或讀出一個其它類型的數(shù)據(jù)(
int,long…
)。字節(jié)序可以用
order
方法來取得和設置:
?
ByteOrder order()
??????
返回
ByteBuffer
的字節(jié)序。
ByteBuffer order(ByteOrder bo)
??????
設置
ByteBuffer
的字節(jié)序。
?
ByteBuffer
另一個特別的地方是可以在它的基礎上得到其它類型的
buffer
。如:
?
CharBuffer asCharBuffer()
為當前的
ByteBuffer
創(chuàng)建一個
CharBuffer
的視圖。在該視圖
buffer
中的讀寫操作會按照
ByteBuffer
的字節(jié)序作用到
ByteBuffer
中的數(shù)據(jù)上。
?
用這類方法創(chuàng)建出來的
buffer
會從
ByteBuffer
的
position
位置開始到
limit
位置結束,可以看作是這段數(shù)據(jù)的視圖。視圖
buffer
的
readOnly
屬性和
direct
屬性與
ByteBuffer
的一致,而且也只有通過這種方法,才可以得到其他數(shù)據(jù)類型的
direct buffer
。
?
ByteOrder
用來表示
ByteBuffer
字節(jié)序的類,可將其看成
java
中的
enum
類型。主要定義了下面幾個
static
方法和屬性:
?
ByteOrder BIG_ENDIAN
??????
代表大字節(jié)序的
ByteOrder
。
ByteOrder LITTLE_ENDIAN
??????
代表小字節(jié)序的
ByteOrder
。
ByteOrder nativeOrder()
??????
返回當前硬件平臺的字節(jié)序。
?
MappedByteBuffer
ByteBuffer
的子類,是文件內容在內存中的映射。這個類的實例需要通過
FileChannel
的
map()
方法來創(chuàng)建。
?
?
接下來看看一個使用
ByteBuffer
的例子,這個例子從標準輸入不停地讀入字符,當讀滿一行后,將收集的字符寫到標準輸出:
???
public
static
void
main(String
[]
args)
??????
throws
IOException
???
{
??????
//
創(chuàng)建一個
capacity
為
256
的
ByteBuffer
??????
ByteBuffer
buf
=
ByteBuffer.allocate(256);
??????
while
(
true
)
{
??????????
//
從標準輸入流讀入一個字符
??????????
int
c
=
System.in.read();
??????????
//
當讀到輸入流結束時,退出循環(huán)
??????????
if
(c
==
-1)
?????????????
break
;
??????????
??????????
//
把讀入的字符寫入
ByteBuffer
中
??????????
buf.put((
byte
)
c);
??????????
//
當讀完一行時,輸出收集的字符
??????????
if
(c
==
'\n'
)
{
?????????????
//
調用
flip()
使
limit
變?yōu)楫斍暗?/span>
position
的值
,position
變?yōu)?/span>
0,
?????????????
//
為接下來從
ByteBuffer
讀取做準備
?????????????
buf.flip();
?????????????
//
構建一個
byte
數(shù)組
?????????????
byte
[]
content
=
new
byte
[buf.limit()];
?????????????
//
從
ByteBuffer
中讀取數(shù)據(jù)到
byte
數(shù)組中
?????????????
buf.get(content);
??????????
???
//
把
byte
數(shù)組的內容寫到標準輸出
?????????????
System.out.print(
new
String(content));
?????????????
//
調用
clear()
使
position
變?yōu)?/span>
0,limit
變?yōu)?/span>
capacity
的值,
?????????????
//
為接下來寫入數(shù)據(jù)到
ByteBuffer
中做準備
?????????????
buf.clear();
??????????
}
??????
}
???
}
|
?
?
Package java.nio.channels
這個包定義了
Channel
的概念,
Channel
表現(xiàn)了一個可以進行
IO
操作的通道(比如,通過
FileChannel
,我們可以對文件進行讀寫操作)。
java.nio.channels
包含了文件系統(tǒng)和網(wǎng)絡通訊相關的
channel
類。這個包通過
Selector
和
SelectableChannel
這兩個類,還定義了一個進行非阻塞(
non-blocking
)
IO
操作的
API
,這對需要高性能
IO
的應用非常重要。
?
下面這張
UML
類圖描述了
java.nio.channels
中
interface
的關系:
?
Channel
Channel
表現(xiàn)了一個可以進行
IO
操作的通道,該
interface
定義了以下方法:
?
boolean isOpen()
??????
該
Channel
是否是打開的。
void close()
??????
關閉這個
Channel
,相關的資源會被釋放。
?
ReadableByteChannel
定義了一個可從中讀取
byte
數(shù)據(jù)的
channel interface
。
?
int read(ByteBuffer dst)
從
channel
中讀取
byte
數(shù)據(jù)并寫到
ByteBuffer
中。返回讀取的
byte
數(shù)。
?
WritableByteChannel
定義了一個可向其寫
byte
數(shù)據(jù)的
channel interface
。
?
int write(ByteBuffer src)
??????
從
ByteBuffer
中讀取
byte
數(shù)據(jù)并寫到
channel
中。返回寫出的
byte
數(shù)。
?
ByteChannel
ByteChannel
并沒有定義新的方法,它的作用只是把
ReadableByteChannel
和
WritableByteChannel
合并在一起。
?
ScatteringByteChannel
繼承了
ReadableByteChannel
并提供了同時往幾個
ByteBuffer
中寫數(shù)據(jù)的能力。
?
GatheringByteChannel
繼承了
WritableByteChannel
并提供了同時從幾個
ByteBuffer
中讀數(shù)據(jù)的能力。
?
InterruptibleChannel
用來表現(xiàn)一個可以被異步關閉的
Channel
。這表現(xiàn)在兩方面:
1.???
當一個
InterruptibleChannel
的
close()
方法被調用時,其它
block
在這個
InterruptibleChannel
的
IO
操作上的線程會接收到一個
AsynchronousCloseException
。
2.???
當一個線程
block
在
InterruptibleChannel
的
IO
操作上時,另一個線程調用該線程的
interrupt()
方法會導致
channel
被關閉,該線程收到一個
ClosedByInterruptException
,同時線程的
interrupt
狀態(tài)會被設置。
?
?
接下來的這張
UML
類圖描述了
java.nio.channels
中類的關系:
?
非阻塞
IO
非阻塞
IO
的支持可以算是
NIO API
中最重要的功能,非阻塞
IO
允許應用程序同時監(jiān)控多個
channel
以提高性能,這一功能是通過
Selector
,
SelectableChannel
和
SelectionKey
這
3
個類來實現(xiàn)的。
?
SelectableChannel
代表了可以支持非阻塞
IO
操作的
channel
,可以將其注冊在
Selector
上,這種注冊的關系由
SelectionKey
這個類來表現(xiàn)(見
UML
圖)。
Selector
這個類通過
select()
函數(shù),給應用程序提供了一個可以同時監(jiān)控多個
IO channel
的方法:
?
應用程序通過調用
select()
函數(shù),讓
Selector
監(jiān)控注冊在其上的多個
SelectableChannel
,當有
channel
的
IO
操作可以進行時,
select()
方法就會返回以讓應用程序檢查
channel
的狀態(tài),并作相應的處理。
?
下面是
JDK 1.4
中非阻塞
IO
的一個例子,這段
code
使用了非阻塞
IO
實現(xiàn)了一個
time server
:
???
private
static
void
acceptConnections(
int
port)
throws
Exception
{
??????
//
打開一個
Selector
??????
Selector
acceptSelector
=
??????????
SelectorProvider.provider().openSelector();
?
??????
//
創(chuàng)建一個
ServerSocketChannel
,這是一個
SelectableChannel
的子類
??????
ServerSocketChannel
ssc
=
ServerSocketChannel.open();
??????
//
將其設為
non-blocking
狀態(tài),這樣才能進行非阻塞
IO
操作
??????
ssc.configureBlocking(
false
);
?
??????
//
給
ServerSocketChannel
對應的
socket
綁定
IP
和端口
??????
InetAddress
lh
=
InetAddress.getLocalHost();
??????
InetSocketAddress
isa
=
new
InetSocketAddress(lh,
port);
??????
ssc.socket().bind(isa);
?
??????
//
將
ServerSocketChannel
注冊到
Selector
上,返回對應的
SelectionKey
??????
SelectionKey
acceptKey
=
??????????
ssc.register(acceptSelector,
SelectionKey.OP_ACCEPT);
?
??????
int
keysAdded
=
0;
?
??????
//
用
select()
函數(shù)來監(jiān)控注冊在
Selector
上的
SelectableChannel
??????
//
返回值代表了有多少
channel
可以進行
IO
操作
(ready for IO)
??????
while
((keysAdded
=
acceptSelector.select())
>
0)
{
??????????
// selectedKeys()
返回一個
SelectionKey
的集合,
??????????
//
其中每個
SelectionKey
代表了一個可以進行
IO
操作的
channel
。
??????????
//
一個
ServerSocketChannel
可以進行
IO
操作意味著有新的
TCP
連接連入了
??????????
Set
readyKeys
=
acceptSelector.selectedKeys();
??????????
Iterator
i
=
readyKeys.iterator();
?
??????????
while
(i.hasNext())
{
?????????????
SelectionKey
sk
=
(SelectionKey)
i.next();
?????????????
//
需要將處理過的
key
從
selectedKeys
這個集合中刪除
?????????????
i.remove();
?????????????
//
從
SelectionKey
得到對應的
channel
?????????????
ServerSocketChannel
nextReady
=
?????????????????
(ServerSocketChannel)
sk.channel();
?????????????
//
接受新的
TCP
連接
?????????????
Socket
s
=
nextReady.accept().socket();
?????????????
//
把當前的時間寫到這個新的
TCP
連接中
?????????????
PrintWriter
out
=
?????????????????
new
PrintWriter(s.getOutputStream(),
true
);
?????????????
Date
now
=
new
Date();
?????????????
out.println(now);
?????????????
//
關閉連接
?????????????
out.close();
??????????
}
??????
}
???
}
|
這是個純粹用于演示的例子,因為只有一個
ServerSocketChannel
需要監(jiān)控,所以其實并不真的需要使用到非阻塞
IO
。不過正因為它的簡單,可以很容易地看清楚非阻塞
IO
是如何工作的。
?
SelectableChannel
這個抽象類是所有支持非阻塞
IO
操作的
channel
(如
DatagramChannel
、
SocketChannel
)的父類。
SelectableChannel
可以注冊到一個或多個
Selector
上以進行非阻塞
IO
操作。
?
SelectableChannel
可以是
blocking
和
non-blocking
模式(所有
channel
創(chuàng)建的時候都是
blocking
模式),只有
non-blocking
的
SelectableChannel
才可以參與非阻塞
IO
操作。
?
SelectableChannel configureBlocking(boolean block)
??????
設置
blocking
模式。
boolean isBlocking()
??????
返回
blocking
模式。
?
通過
register()
方法,
SelectableChannel
可以注冊到
Selector
上。
?
int validOps()
返回一個
bit mask
,表示這個
channel
上支持的
IO
操作。當前在
SelectionKey
中,用靜態(tài)常量定義了
4
種
IO
操作的
bit
值:
OP_ACCEPT
,
OP_CONNECT
,
OP_READ
和
OP_WRITE
。
SelectionKey register(Selector sel, int ops)
將當前
channel
注冊到一個
Selector
上并返回對應的
SelectionKey
。在這以后,通過調用
Selector
的
select()
函數(shù)就可以監(jiān)控這個
channel
。
ops
這個參數(shù)是一個
bit mask
,代表了需要監(jiān)控的
IO
操作。
SelectionKey register(Selector sel, int ops, Object att)
這個函數(shù)和上一個的意義一樣,多出來的
att
參數(shù)會作為
attachment
被存放在返回的
SelectionKey
中,這在需要存放一些
session state
的時候非常有用。
boolean isRegistered()
??????
該
channel
是否已注冊在一個或多個
Selector
上。
?
SelectableChannel
還提供了得到對應
SelectionKey
的方法:
?
SelectionKey keyFor(Selector sel)
返回該
channe
在
Selector
上的注冊關系所對應的
SelectionKey
。若無注冊關系,返回
null
。
?
Selector
Selector
可以同時監(jiān)控多個
SelectableChannel
的
IO
狀況,是非阻塞
IO
的核心。
?
Selector open()
?????? Selector
的一個靜態(tài)方法,用于創(chuàng)建實例。
?
在一個
Selector
中,有
3
個
SelectionKey
的集合:
1.
key set
代表了所有注冊在這個
Selector
上的
channel
,這個集合可以通過
keys()
方法拿到。
2.
Selected-key set
代表了所有通過
select()
方法監(jiān)測到可以進行
IO
操作的
channel
,這個集合可以通過
selectedKeys()
拿到。
3.
Cancelled-key set
代表了已經(jīng)
cancel
了注冊關系的
channel
,在下一個
select()
操作中,這些
channel
對應的
SelectionKey
會從
key set
和
cancelled-key set
中移走。這個集合無法直接訪問。
?
以下是
select()
相關方法的說明:
?
int select()
監(jiān)控所有注冊的
channel
,當其中有注冊的
IO
操作可以進行時,該函數(shù)返回,并將對應的
SelectionKey
加入
selected-key set
。
int select(long timeout)
??????
可以設置超時的
select()
操作。
int selectNow()
??????
進行一個立即返回的
select()
操作。
Selector wakeup()
??????
使一個還未返回的
select()
操作立刻返回。
?
SelectionKey
代表了
Selector
和
SelectableChannel
的注冊關系。
?
Selector
定義了
4
個靜態(tài)常量來表示
4
種
IO
操作,這些常量可以進行位操作組合成一個
bit mask
。
?
int OP_ACCEPT
有新的網(wǎng)絡連接可以
accept
,
ServerSocketChannel
支持這一非阻塞
IO
。
int OP_CONNECT
??????
代表連接已經(jīng)建立(或出錯),
SocketChannel
支持這一非阻塞
IO
。
int OP_READ
int OP_WRITE
??????
代表了讀、寫操作。
?
以下是其主要方法:
?
Object attachment()
返回
SelectionKey
的
attachment
,
attachment
可以在注冊
channel
的時候指定。
Object attach(Object ob)
??????
設置
SelectionKey
的
attachment
。
SelectableChannel channel()
??????
返回該
SelectionKey
對應的
channel
。
Selector selector()
??????
返回該
SelectionKey
對應的
Selector
。
void cancel()
?????? cancel
這個
SelectionKey
所對應的注冊關系。
int interestOps()
??????
返回代表需要
Selector
監(jiān)控的
IO
操作的
bit mask
。
SelectionKey interestOps(int ops)
??????
設置
interestOps
。
int readyOps()
??????
返回一個
bit mask
,代表在相應
channel
上可以進行的
IO
操作。
?
ServerSocketChannel
支持非阻塞操作,對應于
java.net.ServerSocket
這個類,提供了
TCP
協(xié)議
IO
接口,支持
OP_ACCEPT
操作。
?
ServerSocket socket()
??????
返回對應的
ServerSocket
對象。
SocketChannel accept()
??????
接受一個連接,返回代表這個連接的
SocketChannel
對象。
?
SocketChannel
支持非阻塞操作,對應于
java.net.Socket
這個類,提供了
TCP
協(xié)議
IO
接口,支持
OP_CONNECT
,
OP_READ
和
OP_WRITE
操作。這個類還實現(xiàn)了
ByteChannel
,
ScatteringByteChannel
和
GatheringByteChannel
接口。
DatagramChannel
和這個類比較相似,其對應于
java.net.DatagramSocket
,提供了
UDP
協(xié)議
IO
接口。
?
Socket socket()
??????
返回對應的
Socket
對象。
boolean connect(SocketAddress remote)
boolean finishConnect()
connect()
進行一個連接操作。如果當前
SocketChannel
是
blocking
模式,這個函數(shù)會等到連接操作完成或錯誤發(fā)生才返回。如果當前
SocketChannel
是
non-blocking
模式,函數(shù)在連接能立刻被建立時返回
true
,否則函數(shù)返回
false
,應用程序需要在以后用
finishConnect()
方法來完成連接操作。
?
Pipe
包含了一個讀和一個寫的
channel(Pipe.SourceChannel
和
Pipe.SinkChannel)
,這對
channel
可以用于進程中的通訊。
?
FileChannel
用于對文件的讀、寫、映射、鎖定等操作。和映射操作相關的類有
FileChannel.MapMode
,和鎖定操作相關的類有
FileLock
。值得注意的是
FileChannel
并不支持非阻塞操作。
?
Channels
這個類提供了一系列
static
方法來支持
stream
類和
channel
類之間的互操作。這些方法可以將
channel
類包裝為
stream
類,比如,將
ReadableByteChannel
包裝為
InputStream
或
Reader
;也可以將
stream
類包裝為
channel
類,比如,將
OutputStream
包裝為
WritableByteChannel
。
?
?
Package java.nio.charset
這個包定義了
Charset
及相應的
encoder
和
decoder
。下面這張
UML
類圖描述了這個包中類的關系,可以將其中
Charset
,
CharsetDecoder
和
CharsetEncoder
理解成一個
Abstract Factory
模式的實現(xiàn):
?
Charset
代表了一個字符集,同時提供了
factory method
來構建相應的
CharsetDecoder
和
CharsetEncoder
。
?
Charset
提供了以下
static
的方法:
?
SortedMap availableCharsets()
??????
返回當前系統(tǒng)支持的所有
Charset
對象,用
charset
的名字作為
set
的
key
。
boolean isSupported(String charsetName)
??????
判斷該名字對應的字符集是否被當前系統(tǒng)支持。
Charset forName(String charsetName)
??????
返回該名字對應的
Charset
對象。
?
Charset
中比較重要的方法有:
?
String name()
??????
返回該字符集的規(guī)范名。
Set aliases()
??????
返回該字符集的所有別名。
CharsetDecoder newDecoder()
??????
創(chuàng)建一個對應于這個
Charset
的
decoder
。
CharsetEncoder newEncoder()
??????
創(chuàng)建一個對應于這個
Charset
的
encoder
。
?
CharsetDecoder
將按某種字符集編碼的字節(jié)流解碼為
unicode
字符數(shù)據(jù)的引擎。
?
CharsetDecoder
的輸入是
ByteBuffer
,輸出是
CharBuffer
。進行
decode
操作時一般按如下步驟進行:
?
1.
調用
CharsetDecoder
的
reset()
方法。(第一次使用時可不調用)
2.
調用
decode()
方法
0
到
n
次,將
endOfInput
參數(shù)設為
false
,告訴
decoder
有可能還有新的數(shù)據(jù)送入。
3.
調用
decode()
方法最后一次,將
endOfInput
參數(shù)設為
true
,告訴
decoder
所有數(shù)據(jù)都已經(jīng)送入。
4.
調用
decoder
的
flush()
方法。讓
decoder
有機會把一些內部狀態(tài)寫到輸出的
CharBuffer
中。
?
CharsetDecoder reset()
??????
重置
decoder
,并清除
decoder
中的一些內部狀態(tài)。
CoderResult decode(ByteBuffer in, CharBuffer out, boolean endOfInput)
從
ByteBuffer
類型的輸入中
decode
盡可能多的字節(jié),并將結果寫到
CharBuffer
類型的輸出中。根據(jù)
decode
的結果,可能返回
3
種
CoderResult
:
CoderResult.UNDERFLOW
表示已經(jīng)沒有輸入可以
decode
;
CoderResult.OVERFLOW
表示輸出已滿;其它的
CoderResult
表示
decode
過程中有錯誤發(fā)生。根據(jù)返回的結果,應用程序可以采取相應的措施,比如,增加輸入,清除輸出等等,然后再次調用
decode()
方法。
CoderResult flush(CharBuffer out)
有些
decoder
會在
decode
的過程中保留一些內部狀態(tài),調用這個方法讓這些
decoder
有機會將這些內部狀態(tài)寫到輸出的
CharBuffer
中。調用成功返回
CoderResult.UNDERFLOW
。如果輸出的空間不夠,該函數(shù)返回
CoderResult.OVERFLOW
,這時應用程序應該擴大輸出
CharBuffer
的空間,然后再次調用該方法。
CharBuffer decode(ByteBuffer in)
一個便捷的方法把
ByteBuffer
中的內容
decode
到一個新創(chuàng)建的
CharBuffer
中。在這個方法中包括了前面提到的
4
個步驟,所以不能和前
3
個函數(shù)一起使用。
?
decode
過程中的錯誤有兩種:
malformed-input CoderResult
表示輸入中數(shù)據(jù)有誤;
unmappable-character CoderResult
表示輸入中有數(shù)據(jù)無法被解碼成
unicode
的字符。如何處理
decode
過程中的錯誤取決于
decoder
的設置。對于這兩種錯誤,
decoder
可以通過
CodingErrorAction
設置成:
1.
忽略錯誤
2.
報告錯誤。(這會導致錯誤發(fā)生時,
decode()
方法返回一個表示該錯誤的
CoderResult
。)
3.
替換錯誤,用
decoder
中的替換字串替換掉有錯誤的部分。
?
CodingErrorAction malformedInputAction()
??????
返回
malformed-input
的出錯處理。
CharsetDecoder onMalformedInput(CodingErrorAction newAction)
??????
設置
malformed-input
的出錯處理。
CodingErrorAction unmappableCharacterAction()
??????
返回
unmappable-character
的出錯處理。
CharsetDecoder onUnmappableCharacter(CodingErrorAction newAction)
??????
設置
unmappable-character
的出錯處理。
String replacement()
??????
返回
decoder
的替換字串。
CharsetDecoder replaceWith(String newReplacement)
??????
設置
decoder
的替換字串。
?
CharsetEncoder
將
unicode
字符數(shù)據(jù)編碼為特定字符集的字節(jié)流的引擎。其接口和
CharsetDecoder
相類似。
?
CoderResult
描述
encode/decode
操作結果的類。
?
CodeResult
包含兩個
static
成員:
?
CoderResult OVERFLOW
??????
表示輸出已滿
CoderResult UNDERFLOW
??????
表示輸入已無數(shù)據(jù)可用。
?
其主要的成員函數(shù)有:
?
boolean isError()
boolean isMalformed()
boolean isUnmappable()
boolean isOverflow()
boolean isUnderflow()
??????
用于判斷該
CoderResult
描述的錯誤。
?
int length()
??????
返回錯誤的長度,比如,無法被轉換成
unicode
的字節(jié)長度。
void throwException()
??????
拋出一個和這個
CoderResult
相對應的
exception
。
?
CodingErrorAction
表示
encoder/decoder
中錯誤處理方法的類。可將其看成一個
enum
類型。有以下
static
屬性:
?
CodingErrorAction IGNORE
??????
忽略錯誤。
CodingErrorAction REPLACE
??????
用替換字串替換有錯誤的部分。
CodingErrorAction REPORT
報告錯誤,對于不同的函數(shù),有可能是返回一個和錯誤有關的
CoderResult
,也有可能是拋出一個
CharacterCodingException
。
posted on 2007-01-12 20:07
???MengChuChen 閱讀(22295)
評論(1) 編輯 收藏