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