浏览 1335 次
锁定老帖子 主题:来点实用的Java NIO(五)
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2013-12-10
从JDK1.4开始,Java 提供了一系列改进的输入和输出处理的新功能,这些功能被称为新IO,新增了许多用于处理输入,输出的类,这些类都被放在java.nio的包以及子包下,并且对原java.io包中的很多类都以NIO的方式,进行了改写,新增了满足NIO的功能。
新IO和传统的IO有相同的目的,都是用于进行输入和输出的,但新IO使用了不同的方式来处理输入输出,新IO采取的方式是采用内存映射的方式来处理输入输出,新IO将文件或文件中的一段区域映射到内存中,这样就可以像访问内存一样来访问文件了,这种方式类似虚拟内存的概念,通过这种方式来进行输入输出比传统的输入输出要快的多。 Channel(通道)和Buffer(缓冲)是新IO中的两个核心对象,Channel是对传统的输入输出系统的模拟,在新IO系统中所有的数据都要通过通道传输,他们之间的最大区别就是它提供了一个map方法,可以通过该map方法将一块数据映射到内存中,传统的IO是面向流的处理,而新的IO则是面向块的处理。 Buff可以被理解成一个容器,它的本质是一个数组,发送到Channel的所有对象都必须放在Buffer中,而从Channel中,读取的数据也必须先放到Buffer中,除了Channel和Buffer之外,新IO还提供了用于将Unicode字符串映射成字节序列以及逆映射的操作的Charset类,也提供了支持支持非阻塞式的Selector类。 Buffer类的几个方法如下: <table class="bbcode"><tr><td>方法名</td><td>描述<tr><td>capacity()</td><td>返回的buffer的容量大小<tr><td>hasRemaining()</td><td>当前位置position和limit之间是否还有元素可供处理<tr><td>limit()</td><td>返回界限值<tr><td>mark()</td><td>在0和position之间做位置标记<tr><td>position()</td><td>buffer中的position值<tr><td>remaining()</td><td>返回当前位置和界限之间的元素个数<tr><td>reset()</td><td>将位置转到mark所在的位置<tr><td>rewind()</td><td>将位置设置0,取消mark标记<tr><td>put()</td><td>支持批量的数据写入<tr><td>get()</td><td>支持数据读取 </table> 注意,使用put或get访问Buffer中的数据时,分为绝对和相对来种情况: 相对:从Buffer的当前position处开始读取或写入数据,然后将位置的值按处理元素的个数增加 绝对: 直接根据索引向Buffer中读取或写入数据,使用绝对方式访问Buffer里的数据时,并不会影响位置的值。 下面散仙给出测试的例子: <pre name="code" class="java">package com.qin.sanxian.newio; import java.nio.CharBuffer; /** * @author 三劫散仙 * 测试Java 新IO的buffer * * */ public class TestBuffer { public static void main(String[] args)throws Exception { //创建一个Buffer对象,allcote分配的容量为8 CharBuffer buff=CharBuffer.allocate(8); System.out.println("容量:"+buff.capacity()); System.out.println("限制大小,limit: "+buff.limit()); System.out.println("位置: position: "+buff.position()); //放入三个元素 buff.put("a"); buff.put("b"); buff.put("c"); System.out.println("加入三个元素后位置 : "+buff.position()); //此方法是会将limit设置为position的位置,将position的位置为0 buff.flip(); System.out.println("执行filp后,limit的位置:"+buff.limit()); System.out.println("执行filp后,position的位置:"+buff.position()); //取出,第一个元素后 System.out.println(buff.get(0)); System.out.println("position: "+buff.position()); //调用clear方法后 ,将position置为0,limit置为capacity buff.clear(); System.out.println("执行clean后,limit ="+buff.limit()); System.out.println("执行clean后,position = "+buff.position()); System.out.println("执行clear后,缓冲区的内容没有被清除: "+buff.get(0)); System.out.println("执行绝对读取后,position= "+buff.position()); } } </pre> 输出结果如下: <pre name="code" class="java">容量:8 限制大小,limit: 8 位置: position: 0 加入三个元素后位置 : 3 执行filp后,limit的位置:3 执行filp后,position的位置:0 a position: 0 执行clean后,limit =8 执行clean后,position = 0 执行clear后,缓冲区的内容没有被清除: a 执行绝对读取后,position= 0 </pre> Channel与Buffer的简单测试: <pre name="code" class="java">package com.qin.sanxian.newio; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; /** * * Channel测试 * **/ public class TestChannel { public static void main(String[] args) throws Exception{ //read(); // write(); moreRead(); } /** * * 读取一个文件的数据 * 写入到另一个文件里 * **/ public static void read()throws Exception{ File f=new File("F:\\1\\text.txt"); //创建流获取channel对象 FileChannel inChannel=new FileInputStream(f).getChannel(); FileChannel outChannel=new FileOutputStream("abc.txt").getChannel(); //将FileChannel里的数据全部映射成ByteBuffer; MappedByteBuffer buffer=inChannel.map(FileChannel.MapMode.READ_ONLY, 0, f.length()); //将f的数据全部输出 outChannel.write(buffer); buffer.clear();//复原位置 Charset c=Charset.forName("UTF-8"); CharsetDecoder decoder=c.newDecoder();//创建解码器 //解码buffer CharBuffer charBuffer=decoder.decode(buffer); System.out.println(charBuffer); outChannel.close();//关闭流 inChannel.close();//关闭流 } /** * * 写入测试 * */ public static void write()throws Exception{ File f=new File("F:\\1\\text.txt"); //获取一个RandomAccessFile对象 RandomAccessFile raf=new RandomAccessFile(f, "rw"); //获取FileChannel FileChannel channel=raf.getChannel(); //将文件全部映射到内存中 ByteBuffer buffer=channel.map(FileChannel.MapMode.READ_WRITE, 0, f.length()); //控制原来的的指针到最后一步 channel.position(f.length()); channel.write(buffer);//拷贝已有数据 channel.close();//释放资源 raf.close();//关闭流 } /** * 多次读取数据 * * **/ public static void moreRead()throws Exception{ FileInputStream f=new FileInputStream(new File("F:\\1\\text.txt")); //创建一个fileChannel FileChannel channel=f.getChannel(); //定义一个ByteBuffer对象 ByteBuffer buff=ByteBuffer.allocate(103); //将FileChannel的数据放入ByteBuffer中 while(channel.read(buff)!=-1){ buff.flip();//封印未读取的空间 //创建Charset对象 Charset charset=Charset.forName("UTF-8"); //创建解码器对象 CharsetDecoder decoder=charset.newDecoder(); //将字节内容转码 CharBuffer cbuff=decoder.decode(buff); System.out.println(cbuff); //为下一次,读取数据做准备,注意其并不会清空缓存内容 buff.clear(); } channel.close(); f.close(); } } </pre> 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |