netty 系列之:netty 中常用的字符串编码解码器
简介
字符串是我们程序中最常用到的消息格式,也是最简单的消息格式,但是正因为字符串 string 太过简单,不能附加更多的信息,所以在 netty 中选择的是使用 byteBuf 作为最底层的消息传递载体。
虽然底层使用的 ByteBuf,但是对于程序员来说,还是希望能够使用这种最简单的字符串格式,那么有什么简单的方法吗?
以下Java面试题是今年最新的,需要的小伙伴可以后台撩我拿 关键词 “免费”? 即可!
netty 中的字符串编码解码器
为了解决在 netty 的 channel 中传递字符串的问题,netty 提供了针对于字符串的编码和解码器,分别是 StringEncoder 和 StringDecoder。
我们来看下他们是怎么在程序中使用的,首先是将 StringDecoder 和 StringEncoder 加入 channelPipeline 中:
ChannelPipeline pipeline = ...;
// Decoders
pipeline.addLast("frameDecoder", new LineBasedFrameDecoder(80));
pipeline.addLast("stringDecoder", new StringDecoder(CharsetUtil.UTF_8));
// Encoder
pipeline.addLast("stringEncoder", new StringEncoder(CharsetUtil.UTF_8));
复制代码
注意,这里我们在使用 StringDecoder 之前还调用了 LineBasedFrameDecoder,先把数据按行进行分割,然后再进行字符串的读取。
那么有人要问了,decoder 加入了 LineBasedFrameDecoder 预处理,为什么写入的时候没有添加行的分割符呢?
事实上这里有两种处理方式,第一种就是在向 channel 中写入字符串的时候,手动加上行分隔符,如下所示:
void channelRead(ChannelHandlerContext ctx, String msg) {
ch.write("Did you say '" + msg + "'?\n");
}
复制代码
如果不想每次都在 msg 后面加上换行符,那么可以将 StringEncoder 替换成为 LineEncoder,上面的 pipeline 就变成下面这样:
ChannelPipeline pipeline = ...;
// Decoders
pipeline.addLast("frameDecoder", new LineBasedFrameDecoder(80));
pipeline.addLast("stringDecoder", new StringDecoder(CharsetUtil.UTF_8));
// Encoder
pipeline.addLast("lineEncoder", new LineEncoder(LineSeparator.UNIX, CharsetUtil.UTF_8));
复制代码
这样,我们在 handler 中就不需要手动添加换行符了,如下所示:
void channelRead(ChannelHandlerContext ctx, String msg) {
ch.write("Did you say '" + msg + "'?");
}
复制代码
不同平台的换行符
在 unix 和 windows 平台传递过文本文件的朋友可能会遇到一个问题,就是 windows 创建的文本文件,如果在 unix 下面打开的话,会发现每行后面多出了一个特殊字符,这是因为 unix 和 windows 平台定义的换行符是不同的。
在 unix 平台通常使用"\n"来换行,而在 windows 平台则使用""\r\n"来换行。
java 程序因为是跨平台的,写出的程序可能运行在 unix 平台,也可能运行在 windows 平台,所以我们需要有一个办法来获取平台的换行符,netty 提供了一个 LineSeparator 的类来完成这个工作。
LineSeparator 中有三个换行符的定义,分别是:
public static final LineSeparator DEFAULT = new LineSeparator(StringUtil.NEWLINE);
public static final LineSeparator UNIX = new LineSeparator("\n");
public static final LineSeparator WINDOWS = new LineSeparator("\r\n");
复制代码
UNIX 和 WINDOWS 很好理解,他们就是我们刚刚讲到的不同的平台。
那么什么是 DEFAULT 呢?DEFAULT 中传入的 NEWLINE,实际上是从系统属性中获取到的,如果没有获取到,则使用默认的"\n"。
public static final String NEWLINE = SystemPropertyUtil.get("line.separator", "\n");
复制代码
字符串编码的实现
上面我们讲到了和字符串编码解码相关的类分别是 StringEncoder,LineEncoder 和 StringDecoder,我们来详细看下这三个类的实现。
首先是 StringEncoder,StringEncoder 继承了 MessageToMessageEncoder:
public class StringEncoder extends MessageToMessageEncoder<CharSequence>
复制代码
泛型中的 CharSequence 表示 StringEncoder 要 encode 的对象是 CharSequence,也就是字符序列。
虽然大家常用 String 这个类,但是不一定大家都知道 String 其实是 CharSequence 的子类,所以 StringEncoder 也可以编码字符串。
StringEncoder 的编码逻辑很简单,将传入的字符串 msg 转换成为 CharBuffer,然后调用 ByteBufUtil 的 encodeString 方法就可以转换成为 ByteBuf,并加入 out 中去:
protected void encode(ChannelHandlerContext ctx, CharSequence msg, List<Object> out) throws Exception {
if (msg.length() == 0) {
return;
}
out.add(ByteBufUtil.encodeString(ctx.alloc(), CharBuffer.wrap(msg), charset));
}
复制代码
LineEncoder 和 StringEncoder 很类似,它也是继承自 MessageToMessageEncoder:
public class LineEncoder extends MessageToMessageEncoder<CharSequence>
复制代码
不同之处在于 encoder 方法:
protected void encode(ChannelHandlerContext ctx, CharSequence msg, List<Object> out) throws Exception {
ByteBuf buffer = ByteBufUtil.encodeString(ctx.alloc(), CharBuffer.wrap(msg), charset, lineSeparator.length);
buffer.writeBytes(lineSeparator);
out.add(buffer);
}
复制代码
ByteBufUtil 的 encodeString 多了一个 lineSeparator.length 参数,用来预留 lineSeparator 的位置,然后在返回的 ByteBuf 后面加上 lineSeparator 作为最终的输出。
StringDecoder 是和 StringEncoder 相反的过程:
public class StringDecoder extends MessageToMessageDecoder<ByteBuf>
复制代码
这里的 ByteBuf 表示的是要解码的对象是 ByteBuf,我们看下他的解码方法:
protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception {
out.add(msg.toString(charset));
}
复制代码
直接调用 msg.toString 方法即可将 ByteBuf 转换成为字符串。
总结
以上就是 netty 中对字符串的编码解码器,通过使用这几个编码解码器可以大大简化我们的工作。
netty 系列之:netty 中常用的字符串编码解码器相关推荐
- 【读后感】Netty 系列之 Netty 高性能之道 - 相比 Mina 如何 ?
[读后感]Netty 系列之 Netty 高性能之道 - 相比 Mina 如何 ? 太阳火神的美丽人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商 ...
- python数据处理常用函数_Python中常用操作字符串的函数与方法总结
Python中常用操作字符串的函数与方法总结 这篇文章主要介绍了Python中常用操作字符串的函数与方法总结,包括字符串的格式化输出与拼接等基础知识,需要的朋友可以参考下 例如这样一个字符串 Pyth ...
- netty系列之:netty中各不同种类的channel详解
文章目录 简介 ServerChannel和它的类型 Epoll和Kqueue AbstractServerChannel ServerSocketChannel ServerDomainSocket ...
- netty系列之:netty实现http2中的流控制
文章目录 简介 http2中的流控制 netty对http2流控制的封装 Http2FlowController Http2LocalFlowController Http2RemoteFlowCon ...
- Netty系列之Netty基础概念与组件
什么是Netty,Netty各个组件介绍 本部分转载自 Java技术债务[什么是Netty?为什么使用Netty?Netty有哪些组件?] 原文链接:https://blog.csdn.net/qq_ ...
- netty系列之:netty架构概述
文章目录 简介 netty架构图 丰富的Buffer数据机构 零拷贝 统一的API 事件驱动 其他优秀的特性 总结 简介 Netty为什么这么优秀,它在JDK本身的NIO基础上又做了什么改进呢?它的架 ...
- Shell编程—【01】shell中常用的字符串操作
计算字符串长度 ${#string} expr length "$string" v1="i love you" len=`expr length " ...
- netty系列之:netty中的懒人编码解码器
文章目录 简介 netty中的内置编码器 使用codec要注意的问题 netty内置的基本codec base64 bytes compression json marshalling protobu ...
- netty系列之:netty中的frame解码器
简介 netty中的数据是通过ByteBuf来进行传输的,一个ByteBuf中可能包含多个有意义的数据,这些数据可以被称作frame,也就是说一个ByteBuf中可以包含多个Frame. 对于消息的接 ...
最新文章
- asd.equals(s)与s.equals(asd)为什么前者可避免NullPointerException
- server日期函数
- Xamarin Studio支持TypeScript开发
- jclouds的命令行界面
- 等午饭吃过后的dwzjzx
- 2021水电消纳交易电量增长超150% 价格已提高16%
- 【图像处理】MATLAB:点、线、边缘检测
- Kubernetes Node Controller源码分析之配置篇
- python算法之归并排序
- CodeSmith(1):使用和语法简介
- x265 编码一行,以及vbv上溢/下溢之后的处理
- pageHelper.startPage(m,n)的用法
- 数仓(五):数据建模--ER模型/维度建模,概念模型/逻辑模型/ 物理模型
- c/C++笔试题总结
- Python学习笔记--解析式
- iPad pencil充放电曲线研究(娱乐向)
- 如何去高效的学习?怎样克服?
- JPG、GIF、PNG和BMP格式的图片各有什么优点和缺点
- Qtablewidget设置某一列不可编辑
- 浅析Android地理定位(GPS)
热门文章
- Java:微信公众号:现金红包支付
- SpringBoot——使用外置的Tomcat服务器
- 计算机2级软件打不开,小编教你二级网页打不开怎么解决
- HDU 1009 FatMouse' Trade(简单贪心 物品可分割的背包问题)
- 计算机原理教程 pdf,大学计算机组成原理教程(第2版).pdf
- python三维坐标轴单位长度_Matplotlib中三维散点图的z轴缩放和限制
- 海格里斯HEGERLS托盘式四向穿梭车批发定制|24小时全自动无人化立体仓库批量托盘作业
- Windows下mmap的等价实现
- 优达学城机器学习之--支持向量机(SVM)
- SocketTools库版,资源重定向的处理