Channel通道 | 张扎瓦的博客

Channel通道

Channel通道的获取与原理


简介

表示io源与目标打开的连接。Channel类似于传统的流,只不过Channel本身不能直接访问数据,Channel只能与Buffer进行交互。

Channel的主要实现类:FileChannel,SocketChannel,ServerSocketChannel,DatagramChannel

获取通道

使用getChannel()方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public void test1() throws FileNotFoundException {
try(
FileInputStream fileInputStream = new FileInputStream("a.txt");
FileOutputStream fileOutputStream = new FileOutputStream("b.txt");

// 1.获取通道
FileChannel inChannel = fileInputStream.getChannel();
FileChannel outChannel = fileOutputStream.getChannel();
) {
// 2.创建缓冲区
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);

// 3.将通道中的数据存入缓冲区
while (inChannel.read(byteBuffer) != -1) {
byteBuffer.flip(); //切换到读数据模式
outChannel.write(byteBuffer);
byteBuffer.clear(); //清空缓冲区
}

} catch (IOException e) {
e.printStackTrace();
}
}

使用静态open()方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public void test2() {
try(
FileChannel inChannel = FileChannel.open(Paths.get("a.txt"), StandardOpenOption.READ);
FileChannel outChannel = FileChannel.open(Paths.get("b.txt"),
StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.CREATE);
) {
// 内存映射文件
MappedByteBuffer inMappedByteBuffer = inChannel.map(FileChannel.MapMode.READ_ONLY, 0, inChannel.size());
MappedByteBuffer outMappedByteBuffer = outChannel.map(FileChannel.MapMode.READ_WRITE, 0, inChannel.size());

byte[] dst = new byte[inMappedByteBuffer.limit()];
inMappedByteBuffer.get(dst);
outMappedByteBuffer.put(dst);
} catch (IOException e) {
e.printStackTrace();
}
}

使用Files工具类中的静态方法 newByteChannel()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public void test3() {
try (
// 获取Channel,Files只能获取ByteChannel
ByteChannel inChannel = Files.newByteChannel(Paths.get("a.txt"),
StandardOpenOption.READ);
ByteChannel outChannel = Files.newByteChannel(Paths.get("b.txt"),
StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.CREATE);

) {
// 创建缓冲区
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
while (inChannel.read(byteBuffer) != -1) {
byteBuffer.flip();
outChannel.write(byteBuffer);
byteBuffer.clear();
}
} catch (IOException e) {
e.printStackTrace();
}
}

通道之间的互相传输

1
2
3
4
5
6
7
8
9
10
11
12
13
public void test4() {
try (
FileChannel inChannel = FileChannel.open(Paths.get("a.txt"), StandardOpenOption.READ);
FileChannel outChannel = FileChannel.open(Paths.get("b.txt"),
StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.CREATE);
) {
//inChannel.transferTo(0, inChannel.size(), outChannel);
// 或者
outChannel.transferFrom(inChannel, 0, inChannel.size());
} catch (IOException e) {
e.printStackTrace();
}
}

分散读取与聚集写入

分散读取

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public void test5() {
try (
FileChannel fileChannel = FileChannel.open(Paths.get("a.txt"), StandardOpenOption.READ);
) {
// 分配缓冲区
ByteBuffer buffer1 = ByteBuffer.allocate(9);
ByteBuffer buffer2 = ByteBuffer.allocate(6);
ByteBuffer[] byteBuffers = {buffer1, buffer2};
// 分散读取
fileChannel.read(byteBuffers);

for (ByteBuffer byteBuffer : byteBuffers) {
byteBuffer.flip();
System.out.println(byteBuffer + new String(byteBuffer.array()));
}
} catch (IOException e) {
e.printStackTrace();
}
}

聚集写入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public void test6() {
try (
FileChannel inChannel = FileChannel.open(Paths.get("a.txt"), StandardOpenOption.READ);
FileChannel outChannel = FileChannel.open(Paths.get("b.txt"),
StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.CREATE);
) {
ByteBuffer buffer1 = ByteBuffer.allocate(72);
ByteBuffer buffer2 = ByteBuffer.allocate(72);
ByteBuffer[] buffers = {buffer1, buffer2};

inChannel.read(buffers);
for (ByteBuffer buffer : buffers) {
buffer.flip();
}
// 聚集写入
outChannel.write(buffers);

} catch (IOException e) {
e.printStackTrace();
}
}
如果我的文章对您有所帮助,不妨打赏一杯豆浆以资鼓励(○` 3′○)