NIO概述
為什么了有了IO她渴,還需要有NIO?
* NIO在JDK1.4后引入的
* NIO是面向塊(緩沖區(qū))編程匿沛,舊IO是面向流編程
*
* IO ? ? NIO
* 面向流 ? ? ? ? ?面向緩沖區(qū)
* 阻塞IO 非阻塞IO
* 無 ? ? ? ? ? 選擇器
*
* Java中針對IO的一些核心的包和接口、類
*
* java.nio 主要包含了各種與Buffer相關(guān)的類
* java.nio.channel 主要包含了與Channel和Selector相關(guān)的類和接口
* java.nio.charset 主要包含了與編碼相關(guān)的類接口
* java.nio.channels.spi 主要包含了與Channel相關(guān)的服務(wù)提供者編程接口
* javan.nio.charset.spi 主要包含了與charset相關(guān)的服務(wù)提供者編程接口
*
*
* 目前需要掌握的核心就是三個包
* Buffer
* Channel
* CharSet
*
* 面向緩沖區(qū)編程:
*? ? ? ? ?數(shù)據(jù)的讀寫必須經(jīng)過緩沖區(qū)
* ?我們可以使用Buffer所對應(yīng)的子類來數(shù)據(jù)從通道(Channel)流向緩沖區(qū)
* ?從緩沖區(qū)寫到通道叫做讀取緩沖區(qū)
Buffer緩沖區(qū)
Buffer
* Buffer是一個抽象類
* 子類有
*? ? ? ? ?ByteBuffer, CharBuffer, DoubleBuffer, FloatBuffer, IntBuffer, LongBuffer, ShortBuffer
*
* 核心類
*? ? ? ? ?ByteBuffer和CharBuffer
* ByteBuffer有一個子類 MappedByteBuffer
* MappedByteBuffer類能夠?qū)⑽募苯佑成涞絻?nèi)存中凭戴,那么這樣我們就可以像訪問內(nèi)存一樣訪問文件函喉,非常方便
*
* 獲取Buffer
*? ? ? ? ?獲取ByteBuffer
*? ? ? ? ? ? ? ? ?static ByteBuffer allocate(int capacity)
? ? ? ? ? ? ? ? ? ? ? ? ?分配一個新的字節(jié)緩沖區(qū)反璃。
? ? ? ? ? ? ? ?static ByteBuffer allocateDirect(int capacity)
? ? ? ? ? ? ? ? ? ? ? ? ?分配新的直接字節(jié)緩沖區(qū)。
? ? ? ? 二者獲取Buffer的區(qū)別
? ? ? ? 1.創(chuàng)建普通Buffer成本低秃臣,讀寫的效率不高
? ? ? ? 2.因為創(chuàng)建直接Buffer成本高涧衙,所以我們一般用在Buffer生存周期較長的時候使用
? ? ? ? 3.只有ByteBuffer才能夠創(chuàng)建直接Buffer,其他的Buffer對象是不能夠創(chuàng)建
? ? ? ? 4.如果創(chuàng)建了直接Buffer但是我又想要使用其他Buffer的功能奥此,可以將ByteBuffer轉(zhuǎn)換成其他Buffer
? ? ? ?? ? ? ? ? ? ? ? ?asIntBuffer()
* 四個非常重要的概念
*? ? ? ? ?capacity: 緩沖區(qū)的容量弧哎,不可以為負數(shù),一旦創(chuàng)建了就不能夠改變
* ?limit: 無效緩沖區(qū)的第一個位置索引得院,limit后面的數(shù)據(jù)既不可讀傻铣,也不可寫
* ?position : 下一個可以被讀取或者寫入的緩沖區(qū)位置索引
* ?mark: 標記索引,該索引能夠用于下次讀取或者寫入祥绞,它只能夠在0-position之間
* ?
* ?四個系數(shù)的關(guān)系:
* ? ? ? ? ?0 < mark < postion < limit < capacity
* ?
* ?五個方法
* ? ? ? ? ?flip(): 將寫模式切換為讀模式非洲, 將limit的值改為postion的值,同時將postion歸0
* ? ? ? ? ? ? ? ? ? ? ? ? ?特點: 就是為下一次數(shù)據(jù)的讀取做好準備
* ? ? ? ? ?clear(): 將讀模式切換為寫模式蜕径,將limit改為capacity的值两踏,同時將postion歸0
* ? ? ? ? ? ? ? ? ? ? ? ? ?特點: 就是為下一次數(shù)據(jù)的寫入做好準備
* ? ? ? ? ?put(): 相對讀取,向Buffer中存儲數(shù)據(jù)
* ? ? ? ? ?get(): 相對讀取兜喻,從Buffer中獲取數(shù)據(jù)
* ? ? ? ? ?hasRemaining(): 判斷當(dāng)前位置和limit之間是否還有元素可處理
*
* 絕對讀取: get(index) 不會影響position的位置
* 相對讀取: put() get() 會影響梦染,每次讀取一次,指針后移
*/
public class NIODemo02 {
? ? ? ?public static void main(String[] args) {
// ? ? ? ? ? ? ? ?ByteBuffer buffer = ByteBuffer.allocate(5);
// ? ? ? ? ? ? ? ?ByteBuffer buffer2 = ByteBuffer.allocateDirect(10);
? ? ? ? ? ? ? ?CharBuffer buffer = CharBuffer.allocate(8);
? ? ? ? ? ? ? ?// Buffer已經(jīng)準備好了向Buffer中寫數(shù)據(jù) ? ?寫模式
? ? ? ? ? ? ? ?System.out.println("capacity:" + buffer.capacity()); // 8
? ? ? ? ? ? ? ?System.out.println("limit:" + buffer.limit()); // 8
? ? ? ? ? ? ? ?System.out.println("position:" + buffer.position()); // 0
? ? ? ? ? ? ? ?buffer.put('a');
? ? ? ? ? ? ? ?buffer.put('b');
? ? ? ? ? ? ? ?buffer.put('c');
? ? ? ? ? ? ? ?System.out.println("------------------------");
? ? ? ? ? ? ? ?System.out.println("capacity:" + buffer.capacity()); // 8
? ? ? ? ? ? ? ?System.out.println("limit:" + buffer.limit()); // 8
? ? ? ? ? ? ? ?System.out.println("position:" + buffer.position()); // 3
? ? ? ? ? ? ? ?System.out.println("------------------------");
? ? ? ? ? ? ? ?// 切換模式 ?,limit變?yōu)閜osition的位置然后將position變?yōu)?
? ? ? ? ? ? ? ?buffer.flip();
? ? ? ? ? ? ? ?System.out.println("capacity:" + buffer.capacity()); // 8
? ? ? ? ? ? ? ?System.out.println("limit:" + buffer.limit()); // 3
? ? ? ? ? ? ? ?System.out.println("position:" + buffer.position()); // 0
? ? ? ? ? ? ? ?System.out.println("------------------------");
// ? ? ? ? ? ? ? ?char ch = 0;
// ? ? ? ? ? ? ? ?ch = buffer.get();
// ? ? ? ? ? ? ? ?System.out.println(ch);
// ? ? ? ? ? ? ? ?ch = buffer.get();
// ? ? ? ? ? ? ? ?System.out.println(ch);
// ? ? ? ? ? ? ? ?
//// ? ? ? ? ? ? ? ?System.out.println("capacity:" + buffer.capacity()); // 8
//// ? ? ? ? ? ? ? ?System.out.println("limit:" + buffer.limit()); // 3
//// ? ? ? ? ? ? ? ?System.out.println("position:" + buffer.position()); // 2
// ? ? ? ? ? ? ? ?ch = buffer.get();
// ? ? ? ? ? ? ? ?System.out.println(ch);
// ? ? ? ? ? ? ? ?
// ? ? ? ? ? ? ? ?ch = buffer.get();
// ? ? ? ? ? ? ? ?System.out.println(ch);
? ? ? ? ? ? ? ?int ch = 0;
? ? ? ? ? ? ? ?while (buffer.hasRemaining()) {
? ? ? ? ? ? ? ? ? ? ? ?ch = buffer.get();
? ? ? ? ? ? ? ? ? ? ? ?System.out.println((char)ch);
? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ?System.out.println("------------------");
? ? ? ? ? ? ? ?buffer.clear(); // 將postion 清 0 帕识,將limit = capacity
? ? ? ? ? ? ? ?System.out.println("capacity:" + buffer.capacity()); // 8
? ? ? ? ? ? ? ?System.out.println("limit:" + buffer.limit()); // 8
? ? ? ? ? ? ? ?System.out.println("position:" + buffer.position()); // 0
? ? ? ? ? ? ? ?// 注意: 調(diào)用clear方法只是將讀模式改為寫模式泛粹,并不會清空緩沖區(qū)的數(shù)據(jù)
? ? ? ? ? ? ? ?System.out.println(buffer.get(1));
? ? ? ? ? ? ? ?System.out.println("執(zhí)行絕對讀取之后Buffer的position位置:" + buffer.position());
? ? ? ?}
}
Channel通道
* Channel原理類似于傳統(tǒng)的流對象, FileInputStream FileOutputStream
* 但是有兩個主要的區(qū)別
*? ? ? ? ?1.Channel能夠?qū)⒅付ǖ牟糠只蛘呷课募成涞絻?nèi)存中
*? ? ? ? ? ? ? ? ?全部映射
*? ? ? ? ? ? ? ? ? ? ? ? ?MappedByteBuffer
*? ? ? ? ? ? ? ? ?部分文件映射
* ?2.程序如果想要讀取Channel中的數(shù)據(jù)肮疗,不能夠直接讀寫晶姊,必須經(jīng)過Buffer
* ?
* ?Java中為Channel提供了如下常用的類
* ?
* ?FileChannel 和文件相關(guān)的通道
* ?DatagramChannel 和UDP協(xié)議傳輸數(shù)據(jù)相關(guān)的通道
* ?SocketChannel 和TCP協(xié)議相關(guān)的數(shù)據(jù)傳輸通道
* ?ServerSocket 和TCP協(xié)議相關(guān)的數(shù)據(jù)傳輸通道
* ?
* ?獲取FileChannel對象
* ?和文件相關(guān)的普通流有哪些?
* ? ? ? ? ?FileInputStream FileOutputStream RandomAccessFile
* ?常用的方法
* ?read() : 將Channel中的數(shù)據(jù)讀取到Buffer中
* ?write() : 向Buffer中寫入數(shù)據(jù)
* ?map(): 將channel中的數(shù)據(jù)全部或者部分映射到Buffer中
* ? ? ? ? ? ? ? ? ?inChannel.map(mode, position, size)
* ? ? ? ? ? ? ? ? ?MappedByteBuffer mappBuffer = inChannel.map(MapMode.READ_ONLY, 0, srcFile.length());
*/
CharSet字符集
Charset 理解為現(xiàn)實生活的編碼表對象
*/
public class NIODemo05 {
? ? ? ?public static void main(String[] args) throws CharacterCodingException {
? ? ? ? ? ? ? ?// 獲取當(dāng)前JDK所支持的所有編碼類型
// ? ? ? ? ? ? ? ?SortedMap<String, Charset> map = Charset.availableCharsets();
// ? ? ? ? ? ? ? ?
// ? ? ? ? ? ? ? ?for (String key : map.keySet()) {
// ? ? ? ? ? ? ? ? ? ? ? ?Charset charset = map.get(key);
// ? ? ? ? ? ? ? ? ? ? ? ?System.out.println(charset);
// ? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ?// 知道了對應(yīng)JDK認可的字符集別名后,那么我們就可以來獲取對應(yīng)的字符集對象
? ? ? ? ? ? ? ?Charset charset = Charset.forName("GBK");
? ? ? ? ? ? ? ?// 創(chuàng)建編碼器 ?編碼 字符/字符串/字符數(shù)組 --> 字節(jié)
? ? ? ? ? ? ? ?CharsetEncoder encoder = charset.newEncoder();
? ? ? ? ? ? ? ?// 創(chuàng)建解碼器 ?解碼 上述相反
? ? ? ? ? ? ? ?CharsetDecoder decoder = charset.newDecoder();
? ? ? ? ? ? ? ?CharBuffer charBuffer = CharBuffer.allocate(10);
? ? ? ? ? ? ? ?charBuffer.put("abc");
? ? ? ? ? ? ? ?charBuffer.flip();
? ? ? ? ? ? ? ?ByteBuffer byteBuffer = encoder.encode(charBuffer);
? ? ? ? ? ? ? ?for (int i = 0; i < byteBuffer.limit(); i++) {
? ? ? ? ? ? ? ? ? ? ? ?System.out.println(byteBuffer.get(i));
? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ?System.out.println(decoder.decode(byteBuffer));
? ? ? ?}
}