Mina的IoBuffer改造成Netty的ByteBuff

  背景:部标GPS通讯底层全部改造成基于Netty服务器实现的,现将Mina的依赖移除,修改过程中有用到缓冲区的读写。现做了如下修改:

原有基于Mina的IoBuffer对字节读写封装代码如下:

  1 package com.hns.gps.gw.jt808.protocol;
  2 
  3 import com.hns.gps.gw.jt808.utils.Tools;
  4 import org.apache.log4j.Logger;
  5 import org.apache.mina.core.buffer.IoBuffer;
  6 
  7 import java.nio.charset.CharacterCodingException;
  8 import java.nio.charset.Charset;
  9 
 10 public class MyBuffer {
 11     private Logger logger = Logger.getLogger(MyBuffer.class);
 12     IoBuffer buff;
 13 
 14     public MyBuffer() {
 15         buff.setUseDirectBuffer(false);
 16         buff = IoBuffer.allocate(1536);
 17         buff.mark();
 18     }
 19 
 20     public MyBuffer(int len) {
 21         buff.setUseDirectBuffer(false);
 22         buff = IoBuffer.allocate(len);
 23         buff.mark();
 24     }
 25 
 26     public MyBuffer(byte[] bytes) {
 27         if (bytes.length > 1024)
 28             buff = IoBuffer.allocate(bytes.length + 100);
 29         else
 30             buff = IoBuffer.allocate(1024);
 31         buff.mark();
 32         buff.put(bytes);
 33         buff.limit(bytes.length);
 34         buff.reset();
 35     }
 36     public MyBuffer(byte[] bytes, int start, int length) {
 37         buff = IoBuffer.allocate(length);
 38         buff.mark();
 39         buff.put(bytes, start, length);
 40         buff.limit(length);
 41         buff.reset();
 42     }
 43 
 44 
 45     public void clear() {
 46         buff.clear();
 47         buff.mark();
 48     }
 49 
 50     public void put(byte a) {
 51         buff.put(a);
 52     }
 53 
 54     public void put(long a)
 55     {
 56         buff.putLong(a);
 57     }
 58 
 59     public void put(short a) {
 60         buff.putShort(a);
 61     }
 62 
 63     public void put(byte[] a) {
 64         buff.put(a);
 65     }
 66 
 67     public boolean hasRemain() {
 68         return buff.remaining() > 0;
 69     }
 70 
 71     public void put(int a) {
 72         buff.putInt(a);
 73     }
 74 
 75     public void putShort(int a) {
 76         buff.putShort((short) a);
 77     }
 78 
 79     public void put(String str) {
 80         // US-ASCII
 81 
 82         try {
 83             byte[] b = str.getBytes("gbk");
 84             buff.put(b);
 85 
 86         } catch (Exception e) {
 87         //    logger.error(e.getMessage(), e);
 88         }
 89     }
 90 
 91     public void putBcd(String str, int length)
 92     {
 93         byte[] b = BcDToBytes(str,length);
 94         buff.put(b);
 95     }
 96 
 97 
 98     public static String BytesToBcd(byte[] bytes, int start, int len) {
 99         StringBuilder bcd = new StringBuilder();
100         for (int m = 0; m < len; m++) {
101             bcd.append(String.format("%02X", bytes[start + m]));
102         }
103         return bcd.toString();
104     }
105 
106     public static byte[] BcDToBytes(String bcd, int len) {
107         bcd = bcd == null ? "" : bcd;
108         while (bcd.length() < len) {
109             bcd = "0" + bcd;
110         }
111         return Tools.HexString2Bytes(bcd);
112     }
113 
114     public void put(String str, int len) {
115         byte[] result = new byte[len];
116         try {
117             byte[] b = str.getBytes("gbk");
118 
119             System.arraycopy(b, 0, result, 0, b.length);
120 
121             for (int m = b.length; m < len; m++) {
122                 result[m] = 0;
123             }
124             buff.put(result);
125 
126         } catch (Exception e) {
127             //logger.error(e.getMessage(), e);
128         }
129     }
130 
131     public byte get() {
132         return buff.get();
133     }
134 
135     public byte[] gets(int len) {
136         byte[] data = new byte[len];
137         buff.get(data);
138         return data;
139     }
140 
141     public int getInt() {
142         return buff.getInt();
143     }
144 
145     public short getShort() {
146         return buff.getShort();
147     }
148 
149     public long getLong() {
150         return buff.getLong();
151     }
152 
153     // 将data字节型数据转换为0~65535 (0xFFFF 即 WORD)。
154     public int getUnsignedShort() {
155         short t = buff.getShort();
156         return t & 0xffff;
157     }
158 
159     // 将data字节型数据转换为0~255 (0xFF 即BYTE)。
160     public int getUnsignedByte() {
161         return buff.get() & 0x0FF;
162     }
163 
164     public long getUnsignedInt() {
165         return buff.getInt() & 0x0FFFFFFFF;
166     }
167 
168     public String getString() {
169         try {
170             String strTemp = buff
171                     .getString(Charset.forName("GBK").newDecoder());
172             return strTemp;
173         } catch (CharacterCodingException e) {
174             e.printStackTrace();
175         }
176         return "";
177     }
178 
179     public String getString(int len) {
180         try {
181             String strTemp = buff.getString(len, Charset.forName("GBK")
182                     .newDecoder());
183             return strTemp;
184         } catch (CharacterCodingException e) {
185             e.printStackTrace();
186             gets(len);
187         }
188         return "";
189     }
190 
191     public String getBcdString(int len) {
192         byte[] bytes = this.gets(len);
193         StringBuilder bcd = new StringBuilder();
194         for (int m = 0; m < len; m++) {
195             bcd.append(String.format("%02X", bytes[m]));
196         }
197         return bcd.toString();
198     }
199 
200     public byte[] array() {
201         int pos = buff.position();
202         byte[] data = new byte[pos];
203         buff.reset();
204         buff.get(data);
205         return data;
206     }
207 
208     public static void main(String[] args) {
209 
210         IoBuffer ib = IoBuffer.allocate(1024);
211         ib.mark();
212         ib.put((byte) 128);
213         ib.reset();
214         // byte b = ib.get();
215         // int x = b& 0xff;
216         short x = ib.getUnsigned();
217 
218         short y = ib.getUnsigned(0);
219 
220         System.out.println("" + x + "," + y);
221     }
222 
223 }

后修改成Netty版的ByteBuffer操作实现如下:

  1 package com.hns.gps.gw.jt808.protocol;
  2 
  3 import com.hns.gps.gw.jt808.utils.Tools;
  4 import io.netty.buffer.ByteBuf;
  5 import io.netty.buffer.ByteBufAllocator;
  6 import io.netty.util.ReferenceCountUtil;
  7 import io.netty.util.ResourceLeakDetector;
  8 import org.apache.log4j.Logger;
  9 
 10 import java.io.UnsupportedEncodingException;
 11 import java.nio.charset.Charset;
 12 
 13 /**
 14  *  ByteBuffer缓冲区,用Netty实现
 15  *
 16  * @author linys
 17  * @create 2018-06-12
 18  * @since 1.0.0
 19  */
 20 public class ByteBuffer {
 21     private Logger logger = Logger.getLogger(ByteBuffer.class);
 22     protected ByteBuf buff;
 23 
 24     public ByteBuffer() {
 25         buff = ByteBufAllocator.DEFAULT.ioBuffer(1536);
 26         //为了找到ByteBuff没有被释放的原因 (上线关闭)
 27         ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.ADVANCED);
 28     }
 29 
 30     public ByteBuffer(byte[] bytes) {
 31         buff = ByteBufAllocator.DEFAULT.ioBuffer(bytes.length);
 32         buff.writeBytes(bytes);
 33         //为了找到ByteBuff没有被释放的原因 (上线关闭)
 34         ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.ADVANCED);
 35     }
 36 
 37     public ByteBuffer(byte[] bytes, int start, int length) {
 38         buff = ByteBufAllocator.DEFAULT.ioBuffer(length);
 39         buff.writeBytes(bytes, start, length);
 40         //为了找到ByteBuff没有被释放的原因 (上线关闭)
 41         ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.ADVANCED);
 42     }
 43 
 44     public void clear() {
 45         buff.clear();
 46         buff.markWriterIndex();
 47         buff.markReaderIndex();
 48     }
 49 
 50     public void put(byte a) {
 51         buff.writeByte(a);
 52     }
 53 
 54     public void put(long a) {
 55         buff.writeLong(a);
 56     }
 57 
 58     public void put(short a) {
 59         buff.writeShort(a);
 60     }
 61 
 62     public void put(byte[] a) {
 63         buff.writeBytes(a);
 64     }
 65 
 66     public boolean hasRemain() {
 67         return buff.isReadable();
 68     }
 69 
 70     public void put(int a) {
 71         buff.writeInt(a);
 72     }
 73 
 74     public void put(String str) {
 75         // US-ASCII
 76         try {
 77             byte[] b = str.getBytes("gbk");
 78             buff.writeBytes(b);
 79         } catch (UnsupportedEncodingException e) {
 80             logger.error(e.getMessage(), e);
 81         }
 82     }
 83 
 84     public String getBcdString(int len) {
 85         byte[] bytes = this.gets(len);
 86         StringBuilder bcd = new StringBuilder();
 87         for (int m = 0; m < len; m++) {
 88             bcd.append(String.format("%02X", bytes[m]));
 89         }
 90         return bcd.toString();
 91     }
 92 
 93     public void putBcd(String str, int length) {
 94         byte[] b = BcDToBytes(str, length);
 95         buff.writeBytes(b);
 96     }
 97 
 98     public static byte[] BcDToBytes(String bcd, int len) {
 99         bcd = bcd == null ? "" : bcd;
100         while (bcd.length() < len) {
101             bcd = "0" + bcd;
102         }
103         return Tools.HexString2Bytes(bcd);
104     }
105 
106     public static String BytesToBcd(byte[] bytes, int start, int len) {
107         StringBuilder bcd = new StringBuilder();
108         for (int m = 0; m < len; m++) {
109             bcd.append(String.format("%02X", bytes[start + m]));
110         }
111         return bcd.toString();
112     }
113 
114     public void put(String str, int len) {
115         byte[] result = new byte[len];
116         try {
117             byte[] b = str.getBytes("gbk");
118             System.arraycopy(b,0, result,0, b.length);
119             for (int m = b.length; m < len; m++) {
120                 result[m] = 0; //不够位补0
121             }
122             buff.writeBytes(result);
123         } catch (UnsupportedEncodingException e) {
124             logger.error(e.getMessage(), e);
125         }
126     }
127 
128     public byte get() {
129         return buff.readByte();
130     }
131 
132     public short getShort() {
133         return buff.readShort();
134     }
135 
136     public int getInt() {
137         return buff.readInt();
138     }
139 
140     public long getLong() {
141         return buff.readLong();
142     }
143 
144     public double getDouble() {
145         return buff.readDouble();
146     }
147 
148     public byte[] gets(int len) {
149         byte[] data = new byte[len];
150         buff.readBytes(data);
151         return data;
152     }
153 
154     // 将data字节型数据转换为0~255 (0xFF 即BYTE)。
155     public short getUnsignedByte() {
156         return buff.readUnsignedByte();
157     }
158 
159     // 将data字节型数据转换为0~65535 (0xFFFF 即 WORD)。
160     public int getUnsignedShort() {
161         return buff.readUnsignedShort();
162     }
163 
164     public long getUnsignedInt() {
165         return buff.readUnsignedInt();
166     }
167 
168     public String getString() {
169         return buff.toString(Charset.forName("GBK"));
170     }
171 
172     public String getString(int len) {
173         return buff.toString(0, len, Charset.forName("GBK"));
174     }
175 
176     /**
177      * 转换成byte数组
178      * @return
179      */
180     public byte[] toByteArray() {
181         int pos = buff.writerIndex();
182         byte[] data = new byte[pos];
183         buff.readBytes(data);
184         //再次调用重新从头读
185         buff.resetReaderIndex();
186         return data;
187     }
188 
189     /**
190      * 清空释放buff,在buff使用结束后调用
191      * @return
192      */
193     public void release() {
194         this.clear();
195         //释放缓冲区内存
196         ReferenceCountUtil.release(buff);
197     }
198 
199     /**
200      * 转换成byte数组并清空释放buff,在buff使用结束后调用
201      * @return
202      */
203     public byte[] toByteArrayAndRelease() {
204         int pos = buff.writerIndex();
205         byte[] data = new byte[pos];
206         buff.readBytes(data);
207         this.clear();
208         //释放缓冲区内存
209         ReferenceCountUtil.release(buff);
210         return data;
211     }
212 
213 
214 }

总结:处理网络数据的项目中经常需要处理字节数据,Java的ByteBuffer很强大,对于NIO的ByteBuffer字节读写缓冲区操作,Mina和Netty都有封装,IoBuffer基于Java原生ByteBuffer封装而成,ByteBuff则是Netty自己独有的字节数据Buffer,Netty提供了更强大的封装并能实现零拷贝,更加方便我们操作字节缓冲区,推荐使用netty的ByteBuff!代码供大家对ByteBuff的封装参考。

文章封装的代码基于连接:

https://blog.csdn.net/alex_bean/article/details/51251015

https://blog.csdn.net/u010853261/article/details/53690780

https://www.cnblogs.com/zzt-lovelinlin/p/5292608.html

原文地址:https://www.cnblogs.com/lys_013/p/9176037.html