您的位置:首页 > 编程语言 > Java开发

Java 新I/O类库

2014-04-07 00:17 127 查看
// 新I/O类库

// 新的I/O类库,他们位于java.nio包中,其目的在于提高I/O操作的效率,nio是new io的缩写,包中引入4个关键的数据类型

// Buffer:缓冲区,临时存放输入或输出数据

// Charset:具有把Unicode字符编码转换为其他字符编码,以及把其他字符编码转换为Unicode字符编码的功能

// Channel:数据传输通道,能够把Buffer中的数据写到数据汇,或者把数据源的数据读入到Buffer

// Selector:支持异步I/O操作,也称为非阻塞I/O操作,他可以被看成是UNIX中select()函数或Win32中WaitForSingleEvent()函数的面向对象版本,一般在编写

// 服务器程序时需要用到它

// 新I/O类库主要从两个方面来提高I/O操作的效率

// 利用Buffer缓冲区和Channel通道来提高I/O操作的速度,还有就是利用Selector来支持非阻塞I/O操作

// 缓冲器Buffer概述:数据输入和输出比较耗时的操作,缓冲区从两个方面提高I/O操作的效率,1,减少实际的物理读写次数,2缓冲区在创建时被分配内存,这块内存区域一直被重用,这可以减少动态分配和回收内存区域的次数

// 旧I/O类库中的BufferedInputStream,BufferedOutputStream,BufferedWriter和BufferedReader实际都运用了缓冲区,新I/O包公开了Buffer API,使得程序可以直接控制和运用缓冲区,下面是Buffer类的层次结构:

// Buffer-------(ByteBuffer,CharBuffer,DoubleBuffer,FloatBuffer,IntBuffer,LongBuffer,ShortBuffer)------MappedByteBuffer

// 所有缓冲区都有以下属性:

// 容量(capacity):表示该缓冲区可以保存多少数据

// 极限(limit):表示缓冲区的当前终点,不能对缓冲区中超过极限的数据进行读写操作,极限是可以修改的,这有利于缓冲区的重用,例如:假定容量为100缓冲区已填满数据,接着程序在重用缓冲区时,仅仅将10个新的数据写入缓冲区,这时可以

// 将极限设为10,这样就不能访问先前的数据,极限是一个非负整数,不应该大于容量

// 位置(position):表示缓冲区下一个读写单元的位置,每次读写缓冲区的数据时,都会改变位置值,为下一次读写数据做准备,位置是一个非负整数,不应该大于极限

// 容量>=极限>=位置,下面提供了用于改变以上3个属性的方法:

// clear(),把极限设为容量值,再把位置设为0

// flip(),把极限设为位置值,再把位置设为0

// re
4000
wind(),不改变极限,把位置设为0

// Buffer是一个抽象类不能被实例化,共有8个具体的缓冲区类,其中最基本的缓冲区是ByteBuffer,他存放的数据单元是字节,ByteBuffer类并没有提供公共的构造方法,但是提供了两个获得ByteBuffer实例的静态工厂方法

// allocate(int capacity)返回一个ByteBuffer对象,参数capacity指定缓冲区的容量

// directAllocate(int capacity)返回一个ByteBuffer对象,参数capacity指定缓冲区的容量,该方法返回的缓冲区称为直接缓冲区,他与当前操作系统能更好的耦合,因此进一步提高I/O操作的速度

// 但是分配直接缓冲区的代价高昂,因此只有在缓冲区较大并且长期存在,或者需要经常重用时,才使用这种缓冲区

// 除去boolean类型外,每种基本类型都有对应的缓冲区类,都有一个allocate(int capacity),在CharBuffer中存放的数据单元为字符,以此类推,还有一种缓冲区是MappedByteBuffer,他是ByteBuffer的子类,他能

// 使缓冲区和文件的某个区域直接映射:所有具有缓冲区类都提供了读写缓冲区的方法:

// get() 相对读,从缓冲区的当前位置读取一个单元的数据,读取完把位置值加1

// get(int index) 绝对读,从参数index指定的位置读取一个单元的数据

// put() 相对写,向缓冲区的当前位置写入一个单元的数据,写完后把位置值加1

// put(int index) 绝对写,向参数index指定的位置写入一个单元的数据

// 通道channel:通道channel用来连接缓冲区与数据源或数据汇,数据源的数据通过通道到达缓冲区,缓冲区的数据经过通道到达数据汇,

// channel接口声明了两个方法:close关闭通道,isOpen判断通道是否打开,通道在创建时被打开,一旦关闭,就不能重新打开

// 最重要的两个子接口是ReadableByteChannel和WritableByteChannel,前者声明了read(ByteBuffer dst)方法,该方法把数据源的数据读入到参数指定的ByteBuffer缓冲区中

// WritableByteChannel接口声明了write(ByteBuffer src)方法,该方法把参数指定的ByteBuffer缓冲区中的数据写到数据汇中,而ByteChannel接口是一个便利接口,

// 他扩展了ReadableByteChannel和WritableByteChannel接口,因而同时支持读和写操作. ScatteringByteChannel接口扩展了ReadableByteChannel接口,允许分散的读取数据

// 分散读取数据是指单个读取操作能填充多个缓冲区,接口声明了read(ByteBuffer[] dsts)方法,该方法把从数据源读取的数据依次填充到参数指定的ByteBuffer数组的各个ByteBuffer中

// GatheringByteChannel接口扩展了WritableByteChannel接口,允许集中的写入数据,是指把多个缓冲区的数据写到数据汇中,声明了方法write(ByteBuffer[] srcs),该方法依次

// 把参数指定的ByteBuffer数组的每个ByteBuffer中的数据写到数据汇,分散读取数据和集中写入数据能够进一步提高输入和输出操作的速度

// FileChannel类是Channel接口的实现类,代表一个与文件相连的通道,该类实现了ByteChannel,ScatteringByteChannel和GatheringByteChannel接口,支持读操作,写操作,分散读写操作

// FileChannel没有公开构造方法,不能new,不过,在FileInputStream,FileOutputStream和RandomAccessFile类中提供了getChannel()方法,该方法返回相应的FileChannel对象

// 字符编码Charset类概述:提供的方法包括:

// ByteBuffer encode(String str),str指定的字符串转换为当前字符编码,把转换后的当前字符编码存在一个ByteBuffer对象中,并将其返回

// ByteBuffer encode(CharBuffer cb),把参数cb指定的字符缓冲区中的字符转换为当前字符编码,把转换后的当前字符编码存放在一个ByteBuffer对象中,原先的参数cb缓冲区内的字符编码使用Unicode字符编码

// CharBuffer decode(ByteBuffer bb),把参数bb指定的ByteBuffer中的当前字符转换为Unicode字符编码,把转换后的Unicode字符编码存放在一个CharBuffer对象中,将其返回

// Charset还有一个静态方法defaultCharset(),他返回代表本地平台的字符编码的charset对象

// 控制缓存区:缓存区是一块可重用的内存空间,可以利用ByteBuffer类的flip()和clear()方法来控制缓冲区,另一方面,对于单纯的拷贝文件操作,可以用FileChannel类的静态方法transferTo()或者transferFrom()来实现

// 控制缓存区 1.ByteBuffer buff = ByteBuffer.allocate(BSIZE); while(in.read(buff)!=-1){buff.flip();out.write(buff);buff.clear();}

// 拷贝文件: in.transferTo(0,in.size(),out);  out.transferFrom(in,0,in.size);
public class Test20 {
public static void main(String[] args) throws Exception {
System.out.println(Charset.defaultCharset());
final int BSIZE = 1024;
// 获取文件流的通道
FileChannel fc = new FileOutputStream("D:\\test.txt").getChannel();
// 通过文件流的通道,将缓存区的内容输出到文件中
fc.write(ByteBuffer.wrap("你好,".getBytes()));
fc.close();

// 获取随机文件流的通道
fc = new RandomAccessFile("D:\\test.txt", "rw").getChannel();
// 定位位置是最后
fc.position(fc.size());
// 通过随机文件流的通道,将缓存区的内容输出到文件中的最后位置
fc.write(ByteBuffer.wrap("朋友".getBytes()));

// 获取文件输入流的通道
fc = new FileInputStream("D:\\test.txt").getChannel();
// 设置缓冲区的容量
ByteBuffer buff = ByteBuffer.allocate(BSIZE);
// 将文件中的内容通过通道放入缓冲区去
fc.read(buff);
// 极限设置为当前位置值,将缓存区的位置的设置为0,
buff.flip();
// 获取本地平台的字符编码的Charset对象
Charset cs = Charset.defaultCharset();
// 把缓冲区的数据转换为Unicode字符编码,然后打印该编码在本地平台中所对应的字符串。
System.out.println(cs.decode(buff));
fc.close();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Java新IO类库