来点实用的Java NIO(五)

从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类的几个方法如下:

方法名 描述
capacity() 返回的buffer的容量大小
hasRemaining() 当前位置position和limit之间是否还有元素可供处理
limit() 返回界限值
mark() 在0和position之间做位置标记
position() buffer中的position值
remaining() 返回当前位置和界限之间的元素个数
reset() 将位置转到mark所在的位置
rewind() 将位置设置0,取消mark标记
put() 支持批量的数据写入
get() 支持数据读取


注意,使用put或get访问Buffer中的数据时,分为绝对和相对来种情况:
相对:从Buffer的当前position处开始读取或写入数据,然后将位置的值按处理元素的个数增加
绝对: 直接根据索引向Buffer中读取或写入数据,使用绝对方式访问Buffer里的数据时,并不会影响位置的值。

下面散仙给出测试的例子:

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());
		
		
	}

}

输出结果如下:
容量: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


Channel与Buffer的简单测试:
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();
		
	}
	
}




你可能感兴趣的:(java,java NIO,java channel)