ByteBuffer 的 flip 方法,许多人都知道是写操作后,即将要开始读操作,需要flip一把。但是,compact方法,知道的人似乎比较少,它用在什么场景呢?本文就是回答这个问题的。
import java.nio.ByteBuffer;
public class T {
public static void main(String[] args) {
ByteBuffer buf = ByteBuffer.allocate(8);
buf.put((byte)0x00);
buf.put((byte)0x01);
buf.put((byte)0x02);
buf.put((byte)0x03);
System.out.println("连续写入4个:");
System.out.println("\t"+buf);
buf.flip();
System.out.println("Flip后:");
System.out.println("\t"+buf);
byte b0 = buf.get();
byte b1 = buf.get();
System.out.println("连续读出2个:"+b0+" "+b1);
System.out.println("\t"+buf);
buf.compact();
System.out.println("Compact后:(应用场景:上一次读没完,下一次写就开始了)");
System.out.println("\t"+buf);
buf.put((byte)0x04);
buf.put((byte)0x05);
System.out.println("再写入两个数:");
System.out.println("\t"+buf);
buf.flip();
byte b2 = buf.get();
byte b3 = buf.get();
byte b4 = buf.get();
byte b5 = buf.get();
System.out.println("连续读出4个:"+b2+" "+b3+" "+b4+" "+b5);
System.out.println("\t"+buf);
}
}
输出:
连续写入4个:
java.nio.HeapByteBuffer[pos=4 lim=8 cap=8]
Flip后:
java.nio.HeapByteBuffer[pos=0 lim=4 cap=8]
连续读出2个:0 1
java.nio.HeapByteBuffer[pos=2 lim=4 cap=8]
Compact后:(应用场景:上一次读没完,下一次写就开始了)
java.nio.HeapByteBuffer[pos=2 lim=8 cap=8]
再写入两个数:
java.nio.HeapByteBuffer[pos=4 lim=8 cap=8]
连续读出4个:2 3 4 5
java.nio.HeapByteBuffer[pos=4 lim=4 cap=8]
http://www.jarvana.com/jarvana/view/org/apache/mina/mina-core/2.0.0-M2/mina-core-2.0.0-M2-sources.jar!/org/apache/mina/filter/codec/CumulativeProtocolDecoder.java?format=ok
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package org.apache.mina.filter.codec;
import org.apache.mina.core.buffer.IoBuffer;Class search for 'org.apache.mina.core.buffer.IoBuffer'
import org.apache.mina.core.service.TransportMetadata;Class search for 'org.apache.mina.core.service.TransportMetadata'
import org.apache.mina.core.session.AttributeKey;Class search for 'org.apache.mina.core.session.AttributeKey'
import org.apache.mina.core.session.IoSession;Class search for 'org.apache.mina.core.session.IoSession'
/**
* A {@link ProtocolDecoder} that cumulates the content of received
* buffers to a <em>cumulative buffer</em> to help users implement decoders.
* <p>
* If the received {@link IoBuffer} is only a part of a message.
* decoders should cumulate received buffers to make a message complete or
* to postpone decoding until more buffers arrive.
* <p>
* Here is an example decoder that decodes CRLF terminated lines into
* <code>Command</code> objects:
* <pre>
* public class CrLfTerminatedCommandLineDecoder
* extends CumulativeProtocolDecoder {
*
* private Command parseCommand(IoBuffer in) {
* // Convert the bytes in the specified buffer to a
* // Command object.
* ...
* }
*
* protected boolean doDecode(
* IoSession session, IoBuffer in, ProtocolDecoderOutput out)
* throws Exception {
*
* // Remember the initial position.
* int start = in.position();
*
* // Now find the first CRLF in the buffer.
* byte previous = 0;
* while (in.hasRemaining()) {
* byte current = in.get();
*
* if (previous == '\r' && current == '\n') {
* // Remember the current position and limit.
* int position = in.position();
* int limit = in.limit();
* try {
* in.position(start);
* in.limit(position);
* // The bytes between in.position() and in.limit()
* // now contain a full CRLF terminated line.
* out.write(parseCommand(in.slice()));
* } finally {
* // Set the position to point right after the
* // detected line and set the limit to the old
* // one.
* in.position(position);
* in.limit(limit);
* }
* // Decoded one line; CumulativeProtocolDecoder will
* // call me again until I return false. So just
* // return true until there are no more lines in the
* // buffer.
* return true;
* }
*
* previous = current;
* }
*
* // Could not find CRLF in the buffer. Reset the initial
* // position to the one we recorded above.
* in.position(start);
*
* return false;
* }
* }
* </pre>
* <p>
* Please note that this decoder simply forward the call to
* {@link #doDecode(IoSession, IoBuffer, ProtocolDecoderOutput)} if the
* underlying transport doesn't have a packet fragmentation. Whether the
* transport has fragmentation or not is determined by querying
* {@link TransportMetadata}.
*
* @author The Apache MINA Project (dev@mina.apache.org)
* @version $Rev: 671827 $, $Date: 2008-06-26 10:49:48 +0200 (jeu, 26 jun 2008) $
*/
public abstract class CumulativeProtocolDecoder extends ProtocolDecoderAdapter {
private final AttributeKey BUFFER = new AttributeKey(getClass(), "buffer");
/**
* Creates a new instance.
*/
protected CumulativeProtocolDecoder() {
}
/**
* Cumulates content of <tt>in</tt> into internal buffer and forwards
* decoding request to {@link #doDecode(IoSession, IoBuffer, ProtocolDecoderOutput)}.
* <tt>doDecode()</tt> is invoked repeatedly until it returns <tt>false</tt>
* and the cumulative buffer is compacted after decoding ends.
*
* @throws IllegalStateException if your <tt>doDecode()</tt> returned
* <tt>true</tt> not consuming the cumulative buffer.
*/
public void decode(IoSession session, IoBuffer in,
ProtocolDecoderOutput out) throws Exception {
if (!session.getTransportMetadata().hasFragmentation()) {
doDecode(session, in, out);
return;
}
boolean usingSessionBuffer = true;
IoBuffer buf = (IoBuffer) session.getAttribute(BUFFER);
// If we have a session buffer, append data to that; otherwise
// use the buffer read from the network directly.
if (buf != null) {
boolean appended = false;
// Make sure that the buffer is auto-expanded.
if (buf.isAutoExpand()) {
try {
buf.put(in);
appended = true;
} catch (IllegalStateException e) {
// A user called derivation method (e.g. slice()),
// which disables auto-expansion of the parent buffer.
} catch (IndexOutOfBoundsException e) {
// A user disabled auto-expansion.
}
}
if (appended) {
buf.flip();
} else {
// Reallocate the buffer if append operation failed due to
// derivation or disabled auto-expansion.
buf.flip();
IoBuffer newBuf = IoBuffer.allocate(
buf.remaining() + in.remaining()).setAutoExpand(true);
newBuf.order(buf.order());
newBuf.put(buf);
newBuf.put(in);
newBuf.flip();
buf = newBuf;
// Update the session attribute.
session.setAttribute(BUFFER, buf);
}
} else {
buf = in;
usingSessionBuffer = false;
}
for (;;) {
int oldPos = buf.position();
boolean decoded = doDecode(session, buf, out);
if (decoded) {
if (buf.position() == oldPos) {
throw new IllegalStateException(
"doDecode() can't return true when buffer is not consumed.");
}
if (!buf.hasRemaining()) {
break;
}
} else {
break;
}
}
// if there is any data left that cannot be decoded, we store
// it in a buffer in the session and next time this decoder is
// invoked the session buffer gets appended to
if (buf.hasRemaining()) {
if (usingSessionBuffer) {
buf.compact();
} else {
storeRemainingInSession(buf, session);
}
} else {
if (usingSessionBuffer) {
removeSessionBuffer(session);
}
}
}
/**
* Implement this method to consume the specified cumulative buffer and
* decode its content into message(s).
*
* @param in the cumulative buffer
* @return <tt>true</tt> if and only if there's more to decode in the buffer
* and you want to have <tt>doDecode</tt> method invoked again.
* Return <tt>false</tt> if remaining data is not enough to decode,
* then this method will be invoked again when more data is cumulated.
* @throws Exception if cannot decode <tt>in</tt>.
*/
protected abstract boolean doDecode(IoSession session, IoBuffer in,
ProtocolDecoderOutput out) throws Exception;
/**
* Releases the cumulative buffer used by the specified <tt>session</tt>.
* Please don't forget to call <tt>super.dispose( session )</tt> when
* you override this method.
*/
@Override
public void dispose(IoSession session) throws Exception {
removeSessionBuffer(session);
}
private void removeSessionBuffer(IoSession session) {
session.removeAttribute(BUFFER);
}
private void storeRemainingInSession(IoBuffer buf, IoSession session) {
final IoBuffer remainingBuf = IoBuffer.allocate(buf.capacity()).setAutoExpand(true);
remainingBuf.order(buf.order());
remainingBuf.put(buf);
session.setAttribute(BUFFER, remainingBuf);
}
}
分享到:
相关推荐
在MINA框架中,CumulativeProtocolDecoder是一个关键的解码器组件,它在处理网络数据流时扮演着重要角色。本文将深入探讨CumulativeProtocolDecoder的使用及其背后的原理。 CumulativeProtocolDecoder的设计目标是...
HPsocket是一个高性能、跨平台的TCP/UDP/串口通信中间件库,它提供了丰富的API接口和灵活的事件驱动模型,使得用户可以方便地开发自己的网络应用程序。本文将重点介绍如何使用HPsocket的`TcpPackServer`类来实现封包...
MATLAB数字滤波器设计及其在语音信号去噪中的应用:源码详解与报告分享,MATLAB 数字滤波器设计 及其语音信号去噪应用。 (供学习交流)带源码,带注释。 有代码和报告。 ,核心关键词:MATLAB; 数字滤波器设计; 语音信号去噪应用; 源码; 注释; 代码与报告。,"MATLAB数字滤波器设计及其在语音信号去噪中的应用:带源码注释与报告"
COMSOL软件模拟三维电化学腐蚀过程的研究分析,comsol三维电化学腐蚀。 ,核心关键词:Comsol;三维电化学;腐蚀;模型模拟;电化学腐蚀过程。,"Comsol模拟:三维电化学腐蚀过程解析"
基于COMSOL的降雨入渗模型:边坡与渗流边界下的强度折减塑性形变研究,comsol降雨入渗模型,边坡降雨边界与渗流边界 强度折减塑性形变 ,comsol降雨入渗模型; 降雨边界; 渗流边界; 强度折减; 塑性形变,"COMSOL降雨入渗模型:边坡渗流与强度折减塑性形变分析"
2025员工安全意识培训试题及答案.docx
Python自动化办公源码-06在Word表格中将上下行相同内容的单元格自动合并
基于深度学习的神经网络技术在信息通信领域的应用研究.pdf
1.内容概要 通过KNN实现鸢尾花分类,即将新的数据点分配给已知类别中的某一类。该算法的核心思想是通过比较距离来确定最近邻的数据点,然后利用这些邻居的类别信息来决定待分类数据点的类别。 2.KNN算法的伪代码 对未知类别属性的数据集中的每个点依次执行以下操作: (1)计算已知类别数据集中的点与当前点之间的距离; (2)按照距离递增次序排序; (3)选取与当前点距离最小的k个点; (4)确定前k个点所在类别的出现频率; (5)返回前k个点出现频率最高的类别作为当前点的预测分类。 3.数据集说明 代码使用`pandas`库加载了一个名为`iris.arff.csv`的数据集 4.学习到的知识 通过鸢尾花分类学习了KNN算法,选择样本数据集中前k个最相似的数据,就是KNN算法中k的出处。k值过大,会出现分类结果模糊的情况;k值较小,那么预测的标签比较容易受到样本的影响。在实验过程中,不同的k值也会导致分类器的错误率不同。KNN算法精度高、无数据输入的假定,可以免去训练过程。但是对于数据量较多的训练样本,KNN必须保存全部数据集,可能会存在计算的时间复杂度、空间复杂度高的情况,存在维数灾难问
感应电机控制与矢量控制仿真:磁链闭环、转速闭环与电流闭环的综合应用研究,感应电机控制仿真,矢量控制,异步电机仿真,磁链闭环,转速闭环,电流闭环 ,核心关键词:感应电机控制仿真; 矢量控制; 异步电机仿真; 磁链闭环; 转速闭环; 电流闭环,"感应电机矢量控制仿真:磁链、转速、电流三闭环异步电机模拟"
威纶通TK6071IP触摸屏锁屏宏指令程序详解:注释清晰,便于理解与学习,威纶通触摸屏锁屏宏指令程序 ~ 威纶通触摸屏锁屏宏指令程序,TK6071IP触摸屏 利用宏指令程序来控制,宏指令注释清晰,方便理解程序。 具有很好的学习意义和借鉴价值。 ,关键词:威纶通触摸屏;锁屏宏指令程序;TK6071IP触摸屏;宏指令控制;注释清晰;学习借鉴。,威纶通触摸屏宏指令程序:清晰注释,学习借鉴之利器
2025输血相关法律法规试题考核试题及答案.docx
Python游戏编程源码-2048小游戏
2025最新康复医学概论考试题库(含答案).doc
Python自动化办公源码-09用Python批量往Word文档中指定位置添加图片
高品质车载充电器技术解决方案:含原理图、PCB图、C源代码及DSP控制器资料,附赠CDCDC模块资料,车载充电器 3Kw OBC 车载充电器 含原理图、PCB图、C源代码、变压器参数等生产资料。 附赠15kwdcdc模块资料 1、这款产品的方案采用的是dsp2803x系列。 2、原理图和Pcb采用AD绘制。 此方案仅供学习 ,车载充电器; 3Kw OBC; 原理图; PCB图; C源代码; 变压器参数; 生产资料; dsp2803x系列; AD绘制; 15kwdcdc模块资料,3Kw车载充电器方案:DSP2803x系列原理图、PCB图及C源学习包
2025最新康复医学考试题及答案.docx
内容概要:本文介绍了一种用于视频处理的新型卷积神经网络(CNN)加速器。主要创新点在于引入了混合精度计算、跨帧数据重用控制器及引擎,以及混合位宽差帧数据编码解码器。这些特性有效解决了视频帧间的时空相关性和稀疏性带来的挑战,提高了处理速度并降低了功耗和带宽需求。具体来说,通过对连续帧的数据相似度利用,可以在保持高精度的同时减少计算量和内存访问次数;通过多类型稀疏卷积聚类数组实现了对现代稀疏神经网络的支持;并通过混合位宽度编码减少了离芯片外的数据传输量,最高达到68%。 适用人群:从事深度学习硬件加速设计的研究人员和技术爱好者;关注AI边缘计算领域的从业者。 使用场景及目标:适用于自动驾驶汽车摄像头、监控系统等实时视频流应用场景。旨在为开发者提供高效的低能耗解决方案,在有限的时间和资源下完成大量的图像信号处理任务,如跟踪、分类等。 其他说明:文中还详细描述了芯片的设计细节,测试平台构建,以及不同模型(如MobileNet)在网络上的实际性能表现。
COMSOL电化学喷射腐蚀模拟与解析:技术原理及应用实践,comsol电化学喷射腐蚀 ,核心关键词:comsol; 电化学; 喷射腐蚀; 电化学腐蚀。,"电化学喷射腐蚀研究:comsol模拟与解析"
项目已获导师指导并通过的高分毕业设计项目,可作为课程设计和期末大作业,下载即用无需修改,项目完整确保可以运行。 包含:项目源码、数据库脚本、软件工具等,该项目可以作为毕设、课程设计使用,前后端代码都在里面。 该系统功能完善、界面美观、操作简单、功能齐全、管理便捷,具有很高的实际应用价值。 项目都经过严格调试,确保可以运行!可以放心下载 技术组成 语言:java 开发环境:idea 数据库:MySql8.0 部署环境:Tomcat(建议用 7.x 或者 8.x 版本),maven 数据库工具:navicat