3. Channel 基本应用
-
3.1. Channel 概述
NIO 是基于通道(Channel)和缓冲区(Buffer)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中。如图所示:
NIO 中 Channel 的一些具体实现类有:
- 1) FileChannel :从文件中读写数据。
- 2) DatagramChannel :能通过 UDP 读写网络中的数据。
- 3) SocketChannel :能通过 TCP 读写网络中的数据。
- 4) ServerSocketChannel 可以监听新进来的 TCP 连接,像 Web 服务器那样。
正如你所看到的,这些通道涵盖了 UDP 和 TCP 网络 IO,以及文件 IO。
-
3.2. FileChannel 基本应用
借助 Channel 对象(FileChannel 类型),从文件读取数据。代码示例:
案例 1:
@Test
public void testFileChannel()throws Exception{
//构建一个Buffer对象(缓冲区):JVM内存
ByteBuffer buf=ByteBuffer.allocate(1024);
//构建一个文件通道对象(可以读写数据)
FileChannel fChannel=FileChannel.open(Paths.get("data.txt"),
StandardOpenOption.READ);//读模式
//将文件内容读到缓冲区(ByteBuffer)
fChannel.read(buf);
System.out.println("切换buf模式,开始从buf读数据");
System.out.println(buf.position());
//从Buffer中取数据
buf.flip();
System.out.println(buf.position());
System.out.println(new String(buf.array()));
buf.clear();//不是是清除,而将数据标记为脏数据(无用数据)
//释放资源
fChannel.close();
}
结果:
案例 2:
@Test
public void testFileChannel()throws Exception{
//构建一个Buffer对象(缓冲区):JVM内存
ByteBuffer buf=ByteBuffer.allocate(2);
//构建一个文件通道对象(可以读写数据)
FileChannel fChannel= FileChannel.open(Paths.get("data.txt"),StandardOpenOption.READ);//读模式
//将文件内容读到缓冲区(ByteBuffer)
int len=-1;
do{
len=fChannel.read(buf);
System.out.println("切换buf模式,开始从buf读数据");
buf.flip();
//判定缓冲区中是否有剩余数据
while(buf.hasRemaining()){
System.out.print((char)buf.get());//每次都1个字节
}
System.out.println();
buf.clear();//每次读数据应将原数据设置为无效。
}while(len!=-1);
//释放资源
fChannel.close();
}
结果:
-
3.3. SocketChanel 基本应用
Java NIO 中的 SocketChannel 是一个连接到 TCP 网络另一端的通道。可以通过以下 2 种方式创建 SocketChannel:
1) 客户端打开一个 SocketChannel 并连接到互联网上的某台服务器。
2) 服 务 端 一 个 新 连 接 到 达 ServerSocketChannel 时 , 会 创 建 一 个SocketChannel。
基于 channel 实现通讯
代码示例:
Client 代码示例:
SocketChannel socketChannel = SocketChannel.open();
socketChannel.connect(new InetSocketAddress("127.0.0.1", 9999));
String newData = "New String to write to file..." + System.currentTimeMillis();
ByteBuffer buf = ByteBuffer.allocate(48);
buf.clear();
buf.put(newData.getBytes());
buf.flip();
while(buf.hasRemaining()) {
socketChannel.write(buf);
}
socketChannel.close()
Server 端代码实现:
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.socket().bind(new InetSocketAddress(9999));
ByteBuffer byteBuffer=ByteBuffer.allocate(48);
while(true){
SocketChannel socketChannel =serverSocketChannel.accept();
int byteReader = socketChannel.read(byteBuffer);
System.out.println(new String(byteBuffer));
socketChannel.close();
}