- Buffer
Buffer没有构造函数,只能通过static XxxBuffer allocate(int capacity) 来创建一个容量为capacity的XxxBuffer.
package com.ivy.nio; import java.nio.CharBuffer; public class BufferDemo { public static void main(String[] args) { // TODO Auto-generated method stub CharBuffer buffer = CharBuffer.allocate(8); System.out.println("capacity:" + buffer.capacity()); System.out.println("limit:" + buffer.limit()); System.out.println("position:" + buffer.position()); buffer.put("a"); buffer.put("b"); buffer.put("c"); System.out.println("after adding three elements -------"); System.out.println("position:" + buffer.position()); buffer.flip(); System.out.println("after flip -------"); System.out.println("position:" + buffer.position()); System.out.println("position(0):" + buffer.get()); System.out.println("position:" + buffer.position()); buffer.clear(); System.out.println("after clear -------"); System.out.println("limit:" + buffer.limit()); System.out.println("position:" + buffer.position()); System.out.println("position(2):" + buffer.get(2)); System.out.println("position:" + buffer.position()); } }
三个重要概念,容量,界限,位置:
- 容量(capacity):缓冲区的容量,最多可以存多少数据。
- 界限(limit):第一个不应该被读出或写入的缓冲区位置索引,也就是说,位于limit后的数据既不可读,也不可写。
- 位置(position):用于指明下一个可以被读出的或写入到缓冲区位置索引,当读数据时,positon的值恰好等于已经读了多少数据。
当Buffer装入数据解暑后,调用Buffer的flip方法,该方法将limit设置为position所在的位置,将position设为0,这样buffer就为输出数据做好了准备;当Buffer输出数据结束后,Buffer调用clear方法,它并不是清空数据,仅仅将position位置置为0,将limit置为capacity,这样为再次向Buffer中装入数据做好准备。
- 使用Channel
Channel类似于传统的流对象,但与传统的流对象有两个主要区别:
- Channel可以直接将制定文件的部分或全部直接映射成Buffer。
- 程序不能直接访问Channel的数据,包括读取,写入都不行,Channel只能与Buffer进行交互。
所有的Channel都不应该通过构造器来直接创建,而是通过传统的节点InputStream,OutputStream的getChannel方法来返回对应的Channel,不同的节点流获得的Channel不一样。
Channel中最常用的3个方法是map(), read()和write(). map()方法的方法签名为:MappedByteBuffer map(FileChannel.MapMode mode, long position, long size). 第一个参数执行映射时的模式,分别有只读/读写等模式,第二第三个参数用于控制将Channel的哪些数据映射成ByteBuffer。
package com.ivy.nio; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.nio.CharBuffer; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; public class FileChannelDemo { public static void main(String[] args) { // TODO Auto-generated method stub File f = new File("./src/com/ivy/nio/FileChannelDemo.java"); try ( FileChannel inChannel = new FileInputStream(f).getChannel(); FileChannel outChannel = new FileOutputStream("channelOutput.txt").getChannel()) { MappedByteBuffer buffer = inChannel.map(FileChannel.MapMode.READ_ONLY, 0, f.length()); Charset charset = Charset.forName("GBK"); outChannel.write(buffer); buffer.clear(); CharsetDecoder decoder = charset.newDecoder(); CharBuffer charBuffer = decoder.decode(buffer); System.out.println(charBuffer); } catch (IOException ioe) { ioe.printStackTrace(); } } }
package com.ivy.nio; import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; public class RandomFileChannelDemo { public static void main(String[] args) { // TODO Auto-generated method stub File f= new File("channelOutput.txt"); try ( RandomAccessFile raf = new RandomAccessFile(f, "rw"); FileChannel randomChannel = raf.getChannel();) { MappedByteBuffer buffer = randomChannel.map(FileChannel.MapMode.READ_ONLY, 0, f.length()); randomChannel.position(f.length()); randomChannel.write(buffer); } catch (IOException ioe) { ioe.printStackTrace(); } } }
- Charset
package com.ivy.nio; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import java.nio.charset.CharsetEncoder; public class CharsetTransformDemo { public static void main(String[] args) throws Exception { // TODO Auto-generated method stub Charset cn = Charset.forName("GBK"); CharsetEncoder cnEncoder = cn.newEncoder(); CharsetDecoder cnDecoder = cn.newDecoder(); CharBuffer cBuffer = CharBuffer.allocate(8); cBuffer.put("孙"); cBuffer.put("悟"); cBuffer.put("空"); cBuffer.flip(); ByteBuffer bBuffer = cnEncoder.encode(cBuffer); for (int i = 0; i < bBuffer.capacity(); i++) { System.out.print(bBuffer.get(i) + " "); } System.out.println(" " + cnDecoder.decode(bBuffer)); } }
实际上,Charset类也提供了decode(ByteBuffer bb), encode(CharBuffer cb)和encode(String str),也就是说,获取了Charset对象后,如果仅仅需要进行简单的编码解码操作,其实无须创建CharsetEncoder & CharsetDecoder,直接调用Charst的encode和decode方法进行编码和解码就行。
- 文件锁
在NIO中,Java提供了FileLock来支持文件锁。