志宇-NIO之Channel

Channel

channel是什么
Channel 是一种新的 I/O 的访问方式, 就是可以进行传输数据,传输的数据可以是文件也可以是Socket套接字;
程序不能访问Channel,Channel能与Buffer进行交互,即把通道中的数据传递给Buffer,程序再去访问Buffer;
常用的Channel有
FileChannel, 读写文件的通道
SocketChannel/ ServerSocketChannel, 读写 Socket 套接字中的数据
DatagramChannel, 通过 UDP 读写网络数据
Channel简单介绍
常用的三类方法:
map() 创建一个MappedByteBuffer,它继承ByteBuffer
read() 从Channel中读数据写入缓冲区
write() 将缓冲区中的数据写入到Channel中
FileChannel
使用RandomAccessFile类进行包装File获得的FileChannel可以双向读写
FileInputStream对象的getChannel方法创建FileChannel
inChannel.transferTo(0, file.length(), outChannel);
outChannel.transferFrom(inChannel, 0, file.length()); FileChannel特有方法把 inChannel 从 0 开始的所有字节传输到 outchannel 中
ServerSocketChannel 与 SocketChannel
ServerSocketChannel 可以监听新进来的 TCP 连接通道
SocketChannel 是一个连接到 TCP 网络套接字的通道.
ServerSocketChannel.open(); 创建ServerSocketChannel对象SocketChannel.open(); 创建SocketChannel对象
ssc.socket().bind( new InetSocketAddress(port)); 绑定端口
ssc.configureBlocking(false); 设置为非阻塞
SocketChannel sc = ssc.accept(); 接收请求
DatagramChannel
DatagramChannel可以监听新进来的 UDP 连接通道
Scatter散射/Gather聚集
Scatter
在这里插入图片描述

package com.lizhiyu.com;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public class Test {
	public static void main(String[] args) throws IOException {
		ByteBuffer byteBuffer=ByteBuffer.allocate(10);
		ByteBuffer byteBuffer2=ByteBuffer.allocate(10);
		ByteBuffer[] bufferArray={byteBuffer,byteBuffer2};
		FileChannel channel=null;
		//从channel中读取数据
		channel.read(bufferArray);
	}
}

Gather
在这里插入图片描述

package com.lizhiyu.com;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public class Test {
	public static void main(String[] args) throws IOException {
		ByteBuffer byteBuffer=ByteBuffer.allocate(10);
		ByteBuffer byteBuffer2=ByteBuffer.allocate(10);
		ByteBuffer[] bufferArray={byteBuffer,byteBuffer2};
		FileChannel channel=null;
		// 将Buffer中的数据写入到Channel中
		channel.write(bufferArray);
	}
}

FileChannel
MappedByteBuffer的应用

package com.lizhiyu.com;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.CharBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;

public class Test {
	public static void main(String[] args) throws IOException {
		File file=new File("Test.java");
		System.out.println(file.getAbsolutePath());
		if(!file.exists()){
			file.createNewFile();
		}
		//使用inputStream只能获得文件中的数据
		FileChannel inchannel = new FileInputStream(file).getChannel();
		//获得文件只能进行读,因为使用FileInputStream
		MappedByteBuffer mappedByteBuffer = inchannel.map(FileChannel.MapMode.READ_ONLY, 0, file.length());
		//使用outputstream可以对文件进行写操作
		FileChannel outchannel = new FileOutputStream(new File("Test2.java")).getChannel();
		//将缓冲区中的数据写入到Channel中
		outchannel.write(mappedByteBuffer);
		
		//也可以把 buf 中的内容打印出来
		//切换为读模式
		mappedByteBuffer.flip(); 
		//创建字符集
		Charset charset = Charset.defaultCharset();
		//使用默认字符集把 buf 中的字节转换为字符
		CharBuffer decode = charset.decode(mappedByteBuffer);
		System.out.println( decode );
        inchannel.close();
	}
}

使用FileChannel进行文件复制

package com.lizhiyu.com;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public class Test {
	public static void main(String[] args) throws IOException {
		File file=new File("F:\\文档\\study\\workspace\\Test\\src\\com\\lizhiyu\\com\\Test.java");
		File file2=new File("F:\\文档\\study\\workspace\\Test\\src\\com\\lizhiyu\\com\\Test2.java");
		FileChannel inchannel = new FileInputStream(file).getChannel();
		FileChannel outchannel = new FileOutputStream(file2).getChannel();
		//创建直接字节流缓冲区
		ByteBuffer buf = ByteBuffer.allocateDirect(1024);
		//这种方法读写数据不可以,因为缓冲区大小是固定的读取不了大量数据
		//将channel中的数据写入到Channel中
//		inchannel.read(allocateDirect);
//		allocateDirect.flip();
//		//创建字符集
//		Charset charset = Charset.defaultCharset();
//		//使用默认字符集把 buf 中的字节转换为字符
//		CharBuffer decode = charset.decode(allocateDirect);
//		System.out.println(decode);
	
		//从 ihChannel 中读取数据保存到 buf 中
		int readBytes = inchannel.read(buf);
		//当 readBytes 不为-1 时,没有读取到文件末尾
		while( readBytes != -1 ){
		//把 buf 中的内容写到 outChannel 中
		buf.flip(); //切换为坊模式
		outchannel.write(buf);
		buf.clear();
		readBytes = inchannel.read(buf);
		}
		inchannel.close();
		outchannel.close();
	}
}

使用RandomAccessFile可以读可以写

package com.lizhiyu.com;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;

public class Test {
    public static void main(String[] args) throws IOException {
      File file = new File("F:\\文档\\study\\workspace\\Test\\src\\com\\lizhiyu\\com\\Test.java");
      File file2 = new File("F:\\文档\\study\\workspace\\Test\\src\\com\\lizhiyu\\com\\Test2.java");
	  FileChannel fileChannel = new RandomAccessFile(file,"rw").getChannel();
	  FileChannel fileChannel2=new FileOutputStream(file2).getChannel();
	  MappedByteBuffer map = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0, file.length());
	  //将缓冲区中的数据写入到channel中
	  fileChannel2.write(map);
	}
}

使用FileChannel的特有方法

package com.lizhiyu.com;

import java.io.File;
import java.io.FileOutputStream;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;

public class Test {
	//一般使用这个方法相对速度较快
	public static void main(String[] args) {
		//把 out.txt 文件复制到 out3.txt 中
		File file = new File("out.txt");
		try(
		RandomAccessFile raf = new RandomAccessFile(file, "rw");
		FileChannel inChannel = raf.getChannel();
		FileChannel outChannel = new FileOutputStream("out3.txt").getChannel();
		) {
		//把 inChannel从 0 开始的所有字节传输到 outchannel中
		// inChannel.transferTo(0, file.length(), outChannel);
		outChannel.transferFrom(inChannel, 0, file.length());
		} catch (Exception e) {
		} 
		}
}

将多个缓冲区的数据写入到文件中Gather

package com.lizhiyu.com;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public class Test {
    public static void main(String[] args) throws IOException {
      ByteBuffer byteBuffer=ByteBuffer.allocate(1000);
      byteBuffer.put("第一个缓冲区".getBytes());
      byteBuffer.flip();
      ByteBuffer byteBuffer2=ByteBuffer.allocate(1000);
      byteBuffer2.put("第二个缓冲区".getBytes());
      byteBuffer2.flip();
      File file=new File("F:\\文档\\study\\workspace\\Test\\src\\com\\lizhiyu\\com\\Test2.java");      
	  FileChannel fileChannel=new FileOutputStream(file).getChannel();
	  ByteBuffer[] bytebufferArray={byteBuffer,byteBuffer2};
	  //将多个buffer写入到channel中
	  fileChannel.write(bytebufferArray);
	}
}

ServerSocketChannel 与 SocketChannel
Server

package com.lizhiyu.com;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;

public class Server {
   public static void main(String[] args) throws IOException {
	ServerSocketChannel ssc = ServerSocketChannel.open();
	ssc.bind(new InetSocketAddress(8888));
	//设置成为阻塞
	ssc.configureBlocking(true);
	while(true){
		SocketChannel sc = ssc.accept();
		//先给客户端发送一个问候
		ByteBuffer buffer = ByteBuffer.allocate(1024);
		buffer.put("hello, I am from socketServer".getBytes());
		buffer.flip();
		sc.write(buffer);
		//再读取客户端中发送来的内容
		System.out.println("from Sockte Client : " + sc.socket().getRemoteSocketAddress());
		buffer.clear();
		sc.read(buffer); //读取客户端发送的数据保存到 buffer 中
		buffer.flip();
		CharBuffer decode = Charset.defaultCharset().decode(buffer);
		System.out.println( decode );
	}
   }
}

Client

package com.lizhiyu.com;

import java.io.IOException;
import java.io.InputStream;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;

public class Client {
   public static void main(String[] args) throws IOException {
	SocketChannel sc = SocketChannel.open();
	boolean connect = sc.connect(new InetSocketAddress(8888));
	
	//向服务器发送消息
	ByteBuffer buffer = ByteBuffer.wrap("hello, I am from client socket".getBytes());
	while( buffer.hasRemaining()){
	sc.write(buffer);
	}
	
	//获得服务器发送给客户端的消息
	InputStream inputStream = sc.socket().getInputStream();
	ReadableByteChannel newChannel = Channels.newChannel(inputStream);
	buffer.clear();
	newChannel.read(buffer);
	buffer.flip();
	CharBuffer decode = Charset.defaultCharset().decode(buffer);
	System.out.println(decode);
	sc.close();
   }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值