1、Channel概念
通道(Channel):用于源节点与目标节点的连接。在 Java NIO 中负责缓冲区中数据的传输。Channel 本身不存储数据,因此需要配合缓冲区进行传输
2、 Channel主要实现的类
|--FileChannel 本地io
|--SocketChannel TCP网络io
|--ServerSocketChannel TCP网络io
|--DatagramChannel UDP网络io
3、 获取通道
3.1 Java 针对支持通道的类提供了 getChannel() 方法
本地 IO:FileInputStream、FileOutputStream、 RandomAccessFile
网络IO:Socket、ServerSocket、DatagramSocket
//利用通道完成文件的复制(非直接缓冲区)
@Test
public void test1(){
long start = System.currentTimeMillis();
FileInputStream fis = null;
FileOutputStream fos = null;
//①获取通道
FileChannel inChannel = null;
FileChannel outChannel = null;
try {
fis = new FileInputStream("/Users/tentsuuhou/Desktop/01.mp4");
fos = new FileOutputStream("/Users/tentsuuhou/Desktop/09.mp4");
inChannel = fis.getChannel();
outChannel = fos.getChannel();
//②分配指定大小的缓冲区
ByteBuffer buf = ByteBuffer.allocate(1024);
//③将通道中的数据存入缓冲区中
while(inChannel.read(buf) != -1){
buf.flip(); //切换读取数据的模式
//④将缓冲区中的数据写入通道中
outChannel.write(buf);
buf.clear(); //清空缓冲区
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if(outChannel != null){
try {
outChannel.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(inChannel != null){
try {
inChannel.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(fos != null){
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(fis != null){
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
long end = System.currentTimeMillis();
System.out.println("耗费时间为:" + (end - start));
}
我用的是mac系统,01.mp4视频25M左右,第一次复制时间1024ms,然后覆盖重新执行,大概左右在683ms,如果可以,大家可以试试1G以上的视频,看看需要多久
3.2、在 JDK 1.7 中的 NIO.2 针对各个通道提供了静态方法 open()
//使用直接缓冲区完成文件的复制(内存映射文件)
@Test
public void test2(){
long start = System.currentTimeMillis();
FileChannel inChannel = null;
FileChannel outChannel= null;
try {
inChannel = FileChannel.open(Paths.get("/Users/tentsuuhou/Desktop/01.mp4"), StandardOpenOption.READ);
outChannel = FileChannel.open(Paths.get("/Users/tentsuuhou/Desktop/08.mp4"), StandardOpenOption.WRITE, StandardOpenOption.READ, StandardOpenOption.CREATE);
//内存映射文件
MappedByteBuffer inMappedBuf = inChannel.map(MapMode.READ_ONLY, 0, inChannel.size());
MappedByteBuffer outMappedBuf = outChannel.map(MapMode.READ_WRITE, 0, inChannel.size());
//直接对缓冲区进行数据的读写操作
byte[] dst = new byte[inMappedBuf.limit()];
inMappedBuf.get(dst);
outMappedBuf.put(dst);
} catch (IOException e){
e.printStackTrace();
} finally {
try {
inChannel.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
outChannel.close();
} catch (IOException e) {
e.printStackTrace();
}
}
long end = System.currentTimeMillis();
System.out.println("耗费时间为:" + (end - start));
}
第一次:371ms,第二次104ms,证明直接缓冲区比间接缓冲区效率搞了很多。
3.3、在 JDK 1.7 中的 NIO.2 的 Files 工具类的 newByteChannel()
直接字节缓冲区还可以通过FileChannel的map()方法将文件区域直接映射到内存中来创建。该方法返回 MappedByteBuffer 。Java 平台的实现有助于通过 JNI 从本机代码创建直接字节缓冲区。如果以上这些缓冲区 中的某个缓冲区实例指的是不可访问的内存区域,则试图访问该区域不会更改该缓冲区的内容,并且将会在 访问期间或稍后的某个时间导致抛出不确定的异常。
@Test
public void test7(){
long start = System.currentTimeMillis();
FileChannel in = null;
FileChannel out = null;
try {
in = (FileChannel) Files.newByteChannel(Paths.get("/Users/tentsuuhou/Desktop/01.mp4"),StandardOpenOption.READ);
out = (FileChannel) Files.newByteChannel(Paths.get("/Users/tentsuuhou/Desktop/07.mp4"),StandardOpenOption.READ,StandardOpenOption.WRITE,StandardOpenOption.CREATE);
MappedByteBuffer inMap = in.map(MapMode.READ_ONLY,0,in.size());
MappedByteBuffer outMap = out.map(MapMode.READ_WRITE,0,in.size());
byte[] bytes = new byte[inMap.limit()];
//直接对缓冲区进行数据的读写操作
inMap.get(bytes);
outMap.put(bytes);
} catch (IOException i){
i.printStackTrace();
} finally {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
long end = System.currentTimeMillis();
System.out.println(end-start);
}
同样使用的是直接缓冲区,速度和上面基本一致,只不过这个是用newByteChannel() 方法创建通道。
4、通道之间的数据传输
4.1 transferFrom()
4.2 transferTo()
//通道之间的数据传输(直接缓冲区)
@Test
public void test3(){
FileChannel inChannel = null;
FileChannel outChannel = null;
try {
inChannel = FileChannel.open(Paths.get("/Users/tentsuuhou/Desktop/01.mp4"), StandardOpenOption.READ);
outChannel = FileChannel.open(Paths.get("/Users/tentsuuhou/Desktop/06.mp4"), StandardOpenOption.WRITE, StandardOpenOption.READ, StandardOpenOption.CREATE);
//使用下面transferTo 或者 transferFrom 都可以达到目的
//inChannel.transferTo(0, inChannel.size(), outChannel);
outChannel.transferFrom(inChannel, 0, inChannel.size());
} catch (IOException e){
e.printStackTrace();
} finally {
try {
inChannel.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
outChannel.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
5、分散(Scatter)与聚集(Gather)
5.1 分散读取(Scattering Reads):将通道中的数据分散到多个缓冲区中
5.2 聚集写入(Gathering Writes):将多个缓冲区中的数据聚集到通道中
//分散和聚集
@Test
public void test4() throws IOException{
RandomAccessFile raf1 = new RandomAccessFile("1.txt", "rw");
//1. 获取通道
FileChannel channel1 = raf1.getChannel();
//2. 分配指定大小的缓冲区
ByteBuffer buf1 = ByteBuffer.allocate(100);
ByteBuffer buf2 = ByteBuffer.allocate(1024);
//3. 分散读取
ByteBuffer[] bufs = {buf1, buf2};
channel1.read(bufs);
for (ByteBuffer byteBuffer : bufs) {
byteBuffer.flip();
}
System.out.println(new String(bufs[0].array(), 0, bufs[0].limit()));
System.out.println("-----------------");
System.out.println(new String(bufs[1].array(), 0, bufs[1].limit()));
//4. 聚集写入
RandomAccessFile raf2 = new RandomAccessFile("2.txt", "rw");
FileChannel channel2 = raf2.getChannel();
channel2.write(bufs);
}
没有什么效率的问题,只是记住有这么一个功能就好了
6、字符集:Charset
6.1 编码:字符串 -> 字节数组
6.2 解码:字节数组 -> 字符串
//字符集
@Test
public void test6() throws IOException{
Charset cs1 = Charset.forName("utf-8");
//获取编码器
CharsetEncoder ce = cs1.newEncoder();
//获取解码器
CharsetDecoder cd = cs1.newDecoder();
CharBuffer cBuf = CharBuffer.allocate(1024);
cBuf.put("我爱开源中国,作者MuJiuTian!");
cBuf.flip();
//编码
ByteBuffer bBuf = ce.encode(cBuf);
for (int i = 0; i < 36; i++) {
System.out.println(bBuf.get());
}
//解码
bBuf.flip();
CharBuffer cBuf2 = cd.decode(bBuf);
System.out.println(cBuf2.toString());
System.out.println("------------------------------------------------------");
Charset cs2 = Charset.forName("utf-8");
bBuf.flip();
CharBuffer cBuf3 = cs2.decode(bBuf);
System.out.println(cBuf3.toString());
}
相关推荐
1. **Java NIO基础**:Netty基于Java NIO(非阻塞I/O)构建,NIO允许程序选择非阻塞方式读写数据,从而提高处理大量连接的能力。了解Java NIO的基本概念,如通道(Channel)、缓冲区(Buffer)、选择器(Selector)等是...
- **基础篇**: 介绍Netty的基本概念和架构,包括Channel、EventLoop、Pipeline等。 - **进阶篇**: 针对ByteBuf的使用、编码与解码、心跳机制等进行深入解析。 - **源码分析篇**: 分析Netty关键组件的内部实现,如...
基础篇走进Java NIO 第1章 Java的I/O演进之路 第2章 NIO入门 第3章 Netty入门应用 第4章 TCP粘包/拆包问题解析之道 第5章 分隔符和定长解析码器的应用 第6章 编码技术 第7章 MessagePack 编解码 第8章 Google ...
本篇文章将从OSI七层模型、TCP与UDP的异同点、BIO、NIO、AIO的简述以及Netty的基本使用等方面展开讨论。 首先,理解网络通信的基础——OSI七层模型是至关重要的。OSI模型是国际标准化组织提出的一种通信参考模型,...
综上所述,这篇博客可能涵盖了Java基本IO概念、NIO的原理和使用,以及如何使用Mina或Netty构建高性能的网络服务,同时提供了非阻塞服务器和客户端的示例代码。这些内容对于深入理解Java网络编程和提升系统性能至关...
"Java开发程序指南进阶篇"专注于帮助初学者和有一定基础的开发者进一步提升他们的技术能力。这篇指南将深入讲解Java的高级特性,涵盖多线程、集合框架、网络编程、异常处理、反射、I/O流、设计模式等多个核心主题。 ...
本篇将深入探讨"精通并发与Netty"涉及的知识点,并结合"nsq"、"protobuffer"和"NIO"等技术进行扩展。 首先,让我们关注并发编程。并发处理能力是现代系统设计的核心,尤其在多核处理器普及的今天。Java中的并发工具...
本篇文章将深入探讨 Netty 的核心概念、特性以及其在实际开发中的应用。 Netty 框架由 Java 编写,它提供了一套丰富的预构建的组件,如协议解码器、编码器、处理程序和管道,这些组件可以帮助开发者快速、高效地...
1. **事件驱动模型**:Netty 使用非阻塞 I/O(NIO)实现,基于 Java 的 Channel 和 EventLoop 等接口,构建了一个高效的事件驱动模型,使得处理并发连接变得简单。 2. **ByteBuf**:Netty 提供的高效字节缓冲区,...
#### 一、Netty简介与并发模型基础 ##### 1.1 Netty概述 Netty是一个高性能、异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器与客户端。它提供了对TCP、UDP等多种传输层协议的支持,并且...
本篇文章将深入探讨如何利用JBoss Netty创建高效的Web Service客户端和服务端。 首先,我们需要理解Netty的基本工作原理。Netty采用非阻塞I/O模型,基于Java NIO(非阻塞输入/输出)库,允许在网络操作中进行高并发...
这篇基于Netty的WebSocket开发小结将探讨如何使用Netty实现WebSocket服务端和客户端的交互。 首先,我们要理解WebSocket的基本概念。WebSocket协议定义了一种在单个TCP连接上进行全双工通信的协议。它通过在握手...
在描述中提到的"博文链接"指向了ITEYE博主wanqi0821的一篇博客文章,虽然具体内容没有提供,但我们可以推测这篇博客可能涵盖了Netty的基础概念、核心特性以及如何在实际项目中应用Netty。博客通常会提供实用的示例...
4. **JDK NIO实现中的已知问题及Netty的解决方案** 5. **构建第一个Netty应用** 6. **Netty从底层构建** 7. **传输层** 8. **缓冲区** 9. **通道处理器(Channel Handler)** 10. **编解码(Codec)** 11. **提供的通道...
本篇文章将深入探讨Netty的基础知识,帮助读者理解和掌握如何在实际项目中运用Netty。 首先,Netty的核心概念是“通道(Channel)”和“事件处理器(Handler)”。通道是网络连接的抽象,可以代表TCP连接、UDP套接...
在本篇关于“Netty框架学习——第一个Netty应用”的文章中,我们将深入理解如何使用Netty构建一个简单的Echo服务器和客户端。Netty是一个高性能、异步事件驱动的网络应用程序框架,广泛应用于Java领域的服务器开发。...
本篇将深入探讨Netty与WebSocket的结合,以及如何利用Netty构建WebSocket服务器。 首先,Netty是一个高性能、异步事件驱动的网络应用框架,它简化了Java网络编程,特别适合用于创建高并发、低延迟的服务。WebSocket...
本篇将深入探讨Netty的一些核心概念和关键特性,结合Java源代码实例,帮助你更好地理解和应用Netty。 一、Netty概述 Netty是由JBOSS提供的一个开源项目,其设计目标是提供一个灵活、高性能、易用的网络通信框架。...
在IT行业中,网络编程是构建分布式系统和网络应用的基础,而Java NIO(Non-blocking Input/Output)则是Java提供的一种高效、低延迟的I/O模型。本篇文章将深入探讨NIO在连网和异步IO方面的应用,以及如何通过源码...