Channel类似于传统的流对象,但与传统的流对象是有区别的:
- Channel既可以读取数据,也可以写入数据。
- Channel可以直接将指定文件的部分或全部直接映射成Buffer。
- Channel可以异步读取和写入。
- 程序不能直接访问Channel中的数据,包括读取、写入都不行,Channel只能与Buffer进行交互。(Channel总是读取或写入Buffer)
通道实现:
- FileChannel是用于读取和写入文件的数据的Channel
- DatagramChannel是用于支持UDP网络通信的Channel
- ServerSocketChannel、SocketChannel是用于支持TCP网络通信的Channel
- Pipe.SinkChannel、Pipe.SourceChannel是用于支持线程之间通信的管道Channel
- ......
实例
FileChannel inChannel = null;
FileChannel outChannel = null;
try {
File f = new File("a.txt");
//创建FileInputStream,以该文件输入流创建FileChannel
inChannel = new FileInputStream(f)
.getChannel();
//将FileChannel里的全部数据映射成ByteBuffer
MappedByteBuffer buffer = inChannel.map(FileChannel.MapMode.READ_ONLY,
0, f.length());
//使用GBK的字符集来创建解码器
Charset charset = Charset.forName("GBK");
//以文件输出流创建FileBuffer,用以控制输出
outChannel = new FileOutputStream("b.txt")
.getChannel();
//直接将buffer里的数据全部输出
outChannel.write(buffer);
//再次调用buffer的clear()方法,复原limit、position的位置
buffer.clear();
//创建解码器(CharsetDecoder)对象
CharsetDecoder decoder = charset.newDecoder();
//使用解码器将ByteBuffer转换成CharBuffer
CharBuffer charBuffer = decoder.decode(buffer);
//CharBuffer的toString方法可以获取对应的字符串
System.out.println(charBuffer);
} catch (IOException ex) {
ex.printStackTrace();
} finally {
try {
if (inChannel != null)
inChannel.close();
if (outChannel != null)
outChannel.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
Channel可以使用map()方法一次将文件中所有内容映射到内存中,如果担心Channel对应的文件过大,使用map()方法一次将所有的文件内容映射到内存中引起性能下降,Channel和Buffer可以像类似传统的流输入输出的方式反复读取或输出内容。程序如下:
FileChannel fcin = null;
try
{
//创建文件输入流
FileInputStream fis = new FileInputStream("a.txt");
//创建一个FileChannel
fcin = fis.getChannel();
//定义一个ByteBuffer对象,用于多次读取存储
ByteBuffer bbuff = ByteBuffer.allocate(1024);
//将FileChannel中数据放入ByteBuffer中
while( fcin.read(bbuff) != -1 )
{
//锁定Buffer的空白区
bbuff.flip();
//创建Charset对象
Charset charset = Charset.forName("gb2312");
//创建解码器(CharsetDecoder)对象
CharsetDecoder decoder = charset.newDecoder();
//将ByteBuffer的内容转码
CharBuffer cbuff = decoder.decode(bbuff);
System.out.println(cbuff);
//将Buffer初始化,为下一次取数据做准备
bbuff.clear();
}
}
catch (IOException ex)
{
ex.printStackTrace();
}
finally
{
try
{
if (fcin != null)
fcin.close();
}
catch (IOException ex)
{
ex.printStackTrace();
}
}