channels java_JAVA NIO中的Channels和Buffers

前言

Channels和Buffers是JAVA NIO里面比较重要的两个概念,NIO正是基于Channels和Buffers进行数据操作,且数据总是从Channels读取到Buffers,或者从Buffers写入到Channels。

通道(Channel)

NIO中的通道与IO中的流类似,不过流是单向的,而通道是双向的。例如InputStream、OutputStream等都是单向的,一个流只能进行读数据或写数据;而FileChannel、SocketChannel等是双向的,既可以从中读数据,也可以写数据。

通道与流的区别如下:

通道是双向的,可读可写,而流是单向的,只能读或只能写;

通道中的数据是跟Buffer进行交互的,但在面向流的I/O中,数据是直接读/写到流中的;

NIO可以异步读写数据;

以FileChannel为例,如下:

FileChannel

FileChannel是文件写入/读取相关的通道;

产生FileChannel的方式:

从FileOutputStream中获取;

从RandomAccessFile中获取;

从FileInputStream中获取;

下面举个例子,分别从FileOutputStream、RandomAccessFile、FileInputStream中获取文件通道,进行相关写入/读取操作;

packagecom.pichen.io;import java.nio.*;import java.nio.channels.*;import java.io.*;public classGetChannel {private static final int BSIZE = 1024;public static void main(String[] args) throwsException {//创建文件输出字节流

FileOutputStream fos = new FileOutputStream("data.txt");//得到文件通道

FileChannel fc =fos.getChannel();//往通道写入ByteBuffer

fc.write(ByteBuffer.wrap("Some text ".getBytes()));//关闭流

fos.close();//随机访问文件

RandomAccessFile raf = new RandomAccessFile("data.txt", "rw");//得到文件通道

fc =raf.getChannel();//设置通道的文件位置 为末尾

fc.position(fc.size());//往通道写入ByteBuffer

fc.write(ByteBuffer.wrap("Some more".getBytes()));//关闭

raf.close();//创建文件输入流

FileInputStream fs = new FileInputStream("data.txt");//得到文件通道

fc =fs.getChannel();//分配ByteBuffer空间大小

ByteBuffer buff =ByteBuffer.allocate(BSIZE);//从通道中读取ByteBuffer

fc.read(buff);//调用此方法为一系列通道写入或相对获取 操作做好准备

buff.flip();//从ByteBuffer从依次读取字节并打印

while(buff.hasRemaining()){

System.out.print((char) buff.get());

}

fs.close();

}

}

再举个文件复制的例子,有两种方式:

打开一个FileChannel用于读,另一个用于写;

直接调用transferTo或者transferFrom方法传输通道之间的数据;

如下代码示例:

packagecom.pichen.io;import java.nio.*;import java.nio.channels.*;import java.io.*;public classChannelCopy {private static final int BSIZE = 1024;public static void main(String[] args) throwsException {//获取文件输入输出字节流

FileInputStream fis = new FileInputStream("C:\\test.jpg");

FileOutputStream fos= new FileOutputStream("C:\\test_copy.jpg");//从文件输入输出字节流中获取通道

FileChannel fci =fis.getChannel();

FileChannel fco=fos.getChannel();//分配ByteBuffer空间大小

ByteBuffer buffer =ByteBuffer.allocate(BSIZE);//第一种种数据拷贝方式,直接往输入通道写数据

while (fci.read(buffer) != -1) {//为写入操作做准备

buffer.flip();//往输出通道写入buffer

fco.write(buffer);//清空buffer,重置内部指针

buffer.clear();

}//第二种数据拷贝方式,利用transferTo或者transferFrom方式

FileOutputStream fos2 = new FileOutputStream("C:\\test_copy2.jpg");

FileChannel fco2=fos.getChannel();

fci.transferTo(0, fci.size(), fco2);

fis.close();

fos.close();

fos2.close();

}

}

缓冲区(Buffer)

buffer用于与通道进行交互,举个例子如下,这里以ByteBuffer为例;

packagecom.pichen.io;

import java.nio.*;

import java.nio.channels.*;

import java.io.*;

public classGetChannel {

private static final int BSIZE = 1024;

public static void main(String[] args) throwsException {

//随机访问文件

RandomAccessFile raf = new RandomAccessFile("C:\\data.txt", "rw");

//得到文件通道

FileChannel fc =raf.getChannel();

ByteBuffer bf =ByteBuffer.allocate(BSIZE);

int bytesRead = fc.read(bf); //read into buffer.

while (bytesRead != -1) {

//通过flip()方法将Buffer从写模式切换到读模式

bf.flip();

while(bf.hasRemaining()) {

//每次读取一个字节

System.out.print((char) bf.get());

}

//清空缓存,准备往缓存写数据

bf.clear();

bytesRead =fc.read(bf);

}

//关闭

raf.close();

}

}

Buffer基本方法

flip方法:从buffer读数据之前调用,从写模式切换到读模式;

clear:往buffer写数据之前调用,全部清除;

compact:往buffer写数据之前调用,只清除已读取的数据,新写入的数据会添加到未读数据末尾;

Buffer基本属性

capacity:buffer空间大小;

position:读写数据时的指针,指向当前位置;

limit:读数据时,表示当前可读数据的大小;写数据时,即buffer大小=capacity;

Buffer的类型

ByteBuffer

MappedByteBuffer

CharBuffer

DoubleBuffer

FloatBuffer

IntBuffer

LongBuffer

ShortBuffer

Buffer中写数据

从Channel写到Buffer,调用通道的read(Bufferbuffer)方法

put()方法写到Buffer里,调用Buffer的put方法

Buffer中读取数据

从Buffer读取数据到Channel,调用通道的write(Bufferbuffer)方法

使用get()方法从Buffer中读取数据,调用Buffer的get方法

参考:http://ifeve.com/java-nio-all/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值