zoukankan      html  css  js  c++  java
  • Netty之数据编码

    一、概况

      我们在网络编程中会把各种数据转换为byte数组(即字节数组)以便能在网络上传输,最基本的如网络字节序(Little-Endian和Big-Endian),按位或多位数据编码与解码,IP地址的编码与解码,BCD编码与解码,ASCII编码与解码,16进制字符串的编码与解码,有符号数与无符号数的编码与解码等。本篇博文所贴代码并不是最简洁最优化的,只是起到抛砖引玉的效果,不用像博主一样刚入门网络编程时经历那么的曲折,少走些弯路,不过站在此刻回想正是经历了磨砺才会闪耀光泽。

    二、代码实现

    1. 编码工具类

      1 package com.chansen.common.utils;
      2 
      3 
      4 import com.chansen.common.enums.TypeEnum;
      5 import io.netty.buffer.ByteBuf;
      6 import io.netty.buffer.ByteBufAllocator;
      7 import io.netty.buffer.ByteBufUtil;
      8 
      9 import java.util.Arrays;
     10 import java.util.Date;
     11 import java.util.List;
     12 import java.util.Map;
     13 import java.util.stream.Collectors;
     14 import java.util.stream.IntStream;
     15 
     16 /**
     17  * 编码工具类
     18  *
     19  * @author 复姓江山
     20  * @date 
     21  */
     22 public final class EncodeUtils {
     23     
     24 
     25     private EncodeUtils() {
     26     }
     27 
     28 
     29    
     30 
     31    
     32 
     33 
     34     /**
     35      * 组装配置文件所配置的ByteBuf
     36      *
     37      * @param type   枚举类型字符串
     38      * @param param  参数
     39      * @param buf    ByteBuf缓存域
     40      * @param endian 字节序
     41      */
     42     public static void encode(String type, Object param,
     43                               ByteBuf buf, boolean endian) {
     44 
     45         //类型枚举
     46         final TypeEnum typeEnum = TypeEnum.match(type);
     47         //根据不同的类型编码数据
     48         switch (typeEnum) {
     49             //有符号int
     50             case TYPE_INT:
     51                 writeInt(param, buf, endian);
     52                 break;
     53             //无符号int
     54             case TYPE_UINT:
     55                 writeUnSignInt(param, buf, endian);
     56                 break;
     57             //有符号short
     58             case TYPE_SHORT:
     59                 writeShort(param, buf, endian);
     60                 break;
     61             //无符号short
     62             case TYPE_USHORT:
     63                 writeUnSignShort(param, buf, endian);
     64                 break;
     65             //有符号byte
     66             case TYPE_BYTE:
     67                 writeByte(param, buf);
     68                 break;
     69             //无符号byte
     70             case TYPE_UBYTE:
     71                 writeUnSignByte(param, buf);
     72                 break;
     73             //字符串
     74             case TYPE_STRING:
     75                 writeString(param, buf);
     76                 break;
     77             //字符串时间
     78             case TYPE_DATE_STRING:
     79                 writeDateString(param, buf);
     80                 break;
     81             case TYPE_HEX_STRING:
     82                 writeHexString(param, buf);
     83                 break;
     84             case TYPE_BIT:
     85                 writeBit(param, buf);
     86                 break;
     87             case TYPE_MULTI_BIT:
     88                 writeMultiBit(param, buf);
     89                 break;
     90             case TYPE_BCD8421:
     91                 writeBcd8421(param, buf);
     92                 break;
     93         }
     94     }
     95 
     96     /**
     97      * 组装ByteBuff
     98      *
     99      * @param type      枚举类型字符串
    100      * @param param     参数
    101      * @param rangeList 枚举范围
    102      * @param buf       ByteBuf缓存域
    103      * @param endian    字节序
    104      */
    105     public static void encodeEnum(String type, Object param,
    106                                   List<Object> rangeList,
    107                                   ByteBuf buf, boolean endian) {
    108         //枚举数据类型
    109         final TypeEnum typeEnum = TypeEnum.match(type);
    110 
    111         switch (typeEnum) {
    112             case TYPE_ENUM_BYTE:
    113                 writeEnumByte(param, rangeList, buf);
    114                 break;
    115             case TYPE_ENUM_INT:
    116                 writeEnumInt(param, rangeList, buf, endian);
    117                 break;
    118             case TYPE_ENUM_STRING:
    119                 writeEnumString(param, rangeList, buf);
    120                 break;
    121             case TYPE_ENUM_HEX_STRING:
    122                 writeEnumHexString(param, rangeList, buf);
    123                 break;
    124         }
    125 
    126     }
    127 
    128     /**
    129      * 写枚举Hex字符串
    130      *
    131      * @param obj  数据
    132      * @param list 枚举范围
    133      * @param buff ByteBuf缓存区
    134      */
    135     public static void writeEnumHexString(Object obj, List<Object> list, ByteBuf buff) {
    136         for (Object object : list) {
    137             if (object.toString().equals(obj.toString())) {
    138                 writeHexString(obj, buff);
    139             }
    140         }
    141 
    142     }
    143 
    144     /**
    145      * 写枚举字符串
    146      *
    147      * @param obj  数据
    148      * @param list 枚举范围
    149      * @param buff ByteBuf缓存区
    150      */
    151     public static void writeEnumString(Object obj, List<Object> list, ByteBuf buff) {
    152         for (Object object : list) {
    153             if (object.toString().equals(obj.toString())) {
    154                 writeString(obj, buff);
    155             }
    156         }
    157 
    158     }
    159 
    160     /**
    161      * 写枚举int
    162      *
    163      * @param obj  数据
    164      * @param list 枚举范围
    165      * @param buff ByteBuf缓存区
    166      */
    167     public static void writeEnumInt(Object obj, List<Object> list, ByteBuf buff, boolean endian) {
    168         for (Object object : list) {
    169             if (object.toString().equals(obj.toString())) {
    170                 writeInt(obj, buff, endian);
    171             }
    172         }
    173 
    174     }
    175 
    176     /**
    177      * 写枚举byte
    178      *
    179      * @param obj  数据
    180      * @param list 枚举范围
    181      * @param buff ByteBuf缓存区
    182      */
    183     public static void writeEnumByte(Object obj, List<Object> list, ByteBuf buff) {
    184         for (Object object : list) {
    185             if (object.toString().equals(obj.toString())) {
    186                 writeByte(obj, buff);
    187             }
    188         }
    189 
    190     }
    191 
    192     /**
    193      * 写字符串数据
    194      *
    195      * @param obj 值
    196      * @param buf ByteBuf缓存区
    197      */
    198     public static void writeHexString(Object obj, ByteBuf buf) {
    199         String value = (String) obj;
    200         writeHexString(value, buf);
    201     }
    202 
    203     /**
    204      * 写字符串数据
    205      *
    206      * @param value 值
    207      * @param buf   ByteBuf缓存区
    208      */
    209     public static void writeHexString(String value, ByteBuf buf) {
    210         //value is hexDump
    211         final byte[] bytes = ByteBufUtil.decodeHexDump(value);
    212         buf.writeBytes(bytes);
    213     }
    214 
    215     /**
    216      * 写时间字符串数据
    217      *
    218      * @param obj 值
    219      * @param buf ByteBuf缓存区
    220      */
    221     public static void writeDateString(Object obj, ByteBuf buf) {
    222         Date value = (Date) obj;
    223         writeDateString(value, buf);
    224     }
    225 
    226     /**
    227      * 写时间字符串数据
    228      *
    229      * @param obj 值
    230      * @param buf ByteBuf缓存区
    231      */
    232     public static void writeDateString(Date obj, ByteBuf buf) {
    233         String value = DateTimeUtils.getFormatDateTime(obj);
    234         writeString(value, buf);
    235     }
    236 
    237     /**
    238      * 写字符串数据
    239      *
    240      * @param obj 值
    241      * @param buf ByteBuf缓存区
    242      */
    243     public static void writeString(Object obj, ByteBuf buf) {
    244         String value = (String) obj;
    245         writeString(value, buf);
    246     }
    247 
    248 
    249     /**
    250      * 写字符串数据
    251      *
    252      * @param value 值
    253      * @param buf   ByteBuf缓存区
    254      */
    255     public static void writeString(String value, ByteBuf buf) {
    256         final char[] valueChars = value.toCharArray();
    257         if (valueChars.length > 0) {
    258             for (char valueChar : valueChars) {
    259                 buf.writeByte(valueChar);
    260             }
    261         }
    262     }
    263 
    264     /**
    265      * 写int数据
    266      *
    267      * @param obj    值
    268      * @param buf    ByteBuf缓存区
    269      * @param endian 字节序
    270      */
    271     public static void writeInt(Object obj, ByteBuf buf, boolean endian) {
    272         int m = (int) obj;
    273         //小字节序
    274         if (endian) {
    275             buf.writeIntLE(m);
    276         } else {
    277             buf.writeInt(m);
    278         }
    279     }
    280 
    281     /**
    282      * 写无符号byte数据
    283      *
    284      * @param obj 值
    285      * @param buf ByteBuf缓存区
    286      */
    287     public static void writeUnSignByte(Object obj, ByteBuf buf) {
    288         int m = (int) obj;
    289         writeUnSignByte(m, buf);
    290     }
    291 
    292     /**
    293      * 写无符号byte数据
    294      *
    295      * @param m   值
    296      * @param buf ByteBuf缓存区
    297      */
    298     public static void writeUnSignByte(int m, ByteBuf buf) {
    299         writeUnSignByteBase(m, buf);
    300     }
    301 
    302     /**
    303      * 写byte数据
    304      *
    305      * @param obj 值
    306      * @param buf ByteBuf缓存区
    307      */
    308     public static void writeByte(Object obj, ByteBuf buf) {
    309         int m = (int) obj;
    310         assert m <= 127 && m >= -128;
    311         buf.writeByte(m);
    312     }
    313 
    314     /**
    315      * 写无符号short数据
    316      *
    317      * @param obj    值
    318      * @param buf    ByteBuf缓存区
    319      * @param endian 字节序
    320      */
    321     public static void writeUnSignShort(Object obj, ByteBuf buf, boolean endian) {
    322         int m = (int) obj;
    323         assert m >= 0 && m <= 65535;
    324         m &= 0x0FFFF;
    325         writeShort(m, buf, endian);
    326     }
    327 
    328     /**
    329      * 写short数据
    330      *
    331      * @param obj    值
    332      * @param buf    ByteBuf缓存区
    333      * @param endian 字节序
    334      */
    335     public static void writeShort(Object obj, ByteBuf buf, boolean endian) {
    336         int m = (short) obj;
    337         //-32768~32767
    338         assert m >= -32768 && m <= 32767;
    339         writeShort(m, buf, endian);
    340     }
    341 
    342     /**
    343      * 写无符号int数据
    344      *
    345      * @param obj    值
    346      * @param buf    ByteBuf缓存区
    347      * @param endian 字节序
    348      */
    349     public static void writeUnSignInt(Object obj, ByteBuf buf, boolean endian) {
    350         long m = (long) obj;
    351         assert m >= 0 && m < 0x100000000L;
    352         String hexString = Long.toHexString(m);
    353         hexString = fullFillHexString(hexString);
    354         final byte[] bytes = hexEncodeBytes(hexString, 4);
    355         //小字节序
    356         if (endian) {
    357             final byte[] littleBytes = {bytes[3], bytes[2], bytes[1], bytes[0]};
    358             buf.writeBytes(littleBytes);
    359         } else {
    360             buf.writeBytes(bytes);
    361         }
    362     }
    363 
    364     /**
    365      * hex字符串转byte数组
    366      *
    367      * @param hexString hex字符串
    368      * @return byte数组
    369      */
    370     public static byte[] hexEncodeBytes(String hexString, int index) {
    371         final byte[] bytes = ByteBufUtil.decodeHexDump(hexString);
    372         int len = bytes.length;
    373         byte[] bytesTmp = new byte[index];
    374         if (len < index) {
    375             byte[] bt = ByteBufUtil.decodeHexDump("00");
    376             for (int i = 0; i < (index - len); i++) {
    377                 bytesTmp[i] = bt[0];
    378             }
    379         }
    380 
    381         for (int j = bytes.length - 1; j >= 0; j--) {
    382             bytesTmp[--index] = bytes[j];
    383         }
    384         return bytesTmp;
    385     }
    386 
    387     /**
    388      * hex字符串补位处理
    389      *
    390      * @param hexString hex字符串
    391      * @return hex字符串
    392      */
    393     public static String fullFillHexString(String hexString) {
    394         int len = hexString.length();
    395         int mold = len % 2;
    396         return mold > 0 ? "0" + hexString : hexString;
    397     }
    398 
    399     /**
    400      * 写short数据
    401      *
    402      * @param m      数据
    403      * @param buf    ByteBuf
    404      * @param endian 字节序
    405      */
    406     public static void writeShort(int m, ByteBuf buf, boolean endian) {
    407         //小字节序
    408         if (endian) {
    409             buf.writeShortLE(m);
    410         } else {
    411             //大字节序
    412             buf.writeShort(m);
    413         }
    414     }
    415 
    416     /**
    417      * 写多bit位
    418      *
    419      * @param obj 参数
    420      * @param buf ByteBuf
    421      */
    422     public static void writeMultiBit(Object obj, ByteBuf buf) {
    423         int[] arr = (int[]) obj;
    424         writeMultiBit(arr, buf);
    425     }
    426 
    427     /**
    428      * 写多bit位
    429      *
    430      * @param arr  参数
    431      * @param buff ByteBuf
    432      */
    433     public static void writeMultiBit(int[] arr, ByteBuf buff) {
    434         int total = 0;
    435         for (int i : arr) {
    436             int j = 1 << i;
    437             total += j;
    438         }
    439         writeBitBase(total, buff);
    440     }
    441 
    442     /**
    443      * 写bit位
    444      *
    445      * @param obj  参数
    446      * @param buff ByteBuf
    447      */
    448     public static void writeBit(Object obj, ByteBuf buff) {
    449         int value = (int) obj;
    450         writeBit(value, buff);
    451     }
    452 
    453     /**
    454      * 位写bit
    455      *
    456      * @param buff     ByteBuf数据缓存区
    457      * @param bitIndex 置位索引
    458      */
    459     public static void writeBit(int bitIndex, ByteBuf buff) {
    460         int i = 1 << bitIndex;
    461         writeBitBase(i, buff);
    462     }
    463 
    464     /**
    465      * 写bit位基础
    466      *
    467      * @param i    数据
    468      * @param buff ByteBuf数据缓存区
    469      */
    470     private static void writeBitBase(int i, ByteBuf buff) {
    471         //buff容量
    472         final int capacity = buff.capacity();
    473         assert capacity >= 1;
    474         //255
    475         if (i <= 0xff) {
    476             int j = capacity;
    477             --j;
    478             fullFillBytes(buff, j);
    479             buff.writeByte(i);
    480         } else {
    481             writeBitBaseMore(i, buff);
    482         }
    483     }
    484 
    485     /**
    486      * 写bit位基础较大值
    487      *
    488      * @param i    数据
    489      * @param buff ByteBuf数据缓存区
    490      */
    491     private static void writeBitBaseMore(int i, ByteBuf buff) {
    492         final int capacity = buff.capacity();
    493         int j = capacity;
    494         String hexString = Integer.toHexString(i);
    495         hexString = fullFillHexString(hexString);
    496         final byte[] bytes = ByteBufUtil.decodeHexDump(hexString);
    497         assert bytes.length <= capacity;
    498         j -= bytes.length;
    499         fullFillBytes(buff, j);
    500         buff.writeBytes(bytes);
    501     }
    502 
    503     /**
    504      * 填充byte
    505      *
    506      * @param buff ByteBuf
    507      * @param m    循环次数
    508      */
    509     private static void fullFillBytes(ByteBuf buff, int m) {
    510         for (; m > 0; m--) {
    511             buff.writeByte(0x00);
    512         }
    513     }
    514 
    515     /**
    516      * 写BCD码
    517      * <p>
    518      * 4位二进制数表示1位十进制数
    519      * <p>
    520      * 20200905
    521      *
    522      * @param obj  数据
    523      * @param buff ByteBuf数据缓存区
    524      */
    525     public static void writeBcd8421(Object obj, ByteBuf buff) {
    526         String value = (String) obj;
    527         writeBcd8421(value, buff);
    528     }
    529 
    530     /**
    531      * 写BCD码
    532      * <p>
    533      * 4位二进制数表示1位十进制数
    534      * <p>
    535      * 20200905
    536      *
    537      * @param bcdString 数据
    538      * @param buff      ByteBuf数据缓存区
    539      */
    540     public static void writeBcd8421(String bcdString, ByteBuf buff) {
    541         assert bcdString.length() == buff.capacity() * 2;
    542         final char[] chars = bcdString.toCharArray();
    543         boolean flag = true;
    544         int j = 0;
    545         for (char ch : chars) {
    546             int i = Integer.parseInt(ch + "");
    547             if (flag) {
    548                 j = i << 4;
    549                 flag = false;
    550             } else {
    551                 j += i;
    552                 writeUnSignByteBase(j, buff);
    553                 j = 0;
    554                 flag = true;
    555             }
    556         }
    557     }
    558 
    559     /**
    560      * 写无符号数基础
    561      *
    562      * @param m    数据
    563      * @param buff ByteBuf数据缓存区
    564      */
    565     private static void writeUnSignByteBase(int m, ByteBuf buff) {
    566         assert m < 256 && m >= 0;
    567         buff.writeByte(m);
    568     }
    569 
    570 }

    2.数据类型枚举类

      1 package com.chansen.common.enums;
      2 
      3 /**
      4  * 数据枚举
      5  *
      6  * @author 复姓江山
      7  * @date 
      8  */
      9 public enum TypeEnum {
     10     /**
     11      * 字符串
     12      */
     13     TYPE_STRING("string"),
     14 
     15     /**
     16      * Binary-Coded Decimal
     17      * bcd码 8421码
     18      * 4位二进制数表示1位十进制数
     19      */
     20     TYPE_BCD8421("bcd8421"),
     21     /**
     22      * 时间字符串
     23      */
     24     TYPE_DATE_STRING("date_string"),
     25     /**
     26      * 枚举byte
     27      */
     28     TYPE_ENUM_BYTE("enum|byte"),
     29 
     30     /**
     31      * 枚举int
     32      */
     33     TYPE_ENUM_INT("enum|int"),
     34 
     35     /**
     36      * 枚举字符串
     37      */
     38     TYPE_ENUM_STRING("enum|string"),
     39 
     40     /**
     41      * 枚举HEX字符串
     42      */
     43     TYPE_ENUM_HEX_STRING("enum|hex_string"),
     44 
     45     /**
     46      * HEX字符串
     47      */
     48     TYPE_HEX_STRING("hex_string"),
     49 
     50     /**
     51      * -2^31~2^31-1
     52      * -2,147,483,648~2,147,483,647
     53      */
     54     TYPE_INT("int"),
     55     /**
     56      * 0~2^32
     57      * 0~4294967296L
     58      */
     59     TYPE_UINT("uint"),
     60     /**
     61      * -2^15~2^15-1
     62      * -32768~32767
     63      */
     64     TYPE_SHORT("short"),
     65     /**
     66      * 0~65535
     67      */
     68     TYPE_USHORT("ushort"),
     69     /**
     70      * -2^7~2^7-1
     71      * -128~127
     72      */
     73     TYPE_BYTE("byte"),
     74 
     75     /**
     76      * 0~256
     77      */
     78     TYPE_UBYTE("ubyte"),
     79 
     80     /**
     81      * 多位同选
     82      */
     83     TYPE_MULTI_BIT("multi_bit"),
     84     /**
     85      * 位
     86      */
     87     TYPE_BIT("bit");
     88 
     89     private String val;
     90 
     91     TypeEnum(String val) {
     92         this.val = val;
     93     }
     94 
     95 
     96     /**
     97      * 字符串匹配枚举类型
     98      *
     99      * @param value 字符串
    100      * @return 对应枚举
    101      */
    102     public static TypeEnum match(String value) {
    103         String str = "TYPE_";
    104         if (value.indexOf("|") > 0) {
    105             value = value.replace("|", "_");
    106         }
    107         str += value.toUpperCase();
    108         return valueOf(str);
    109     }
    110 
    111 
    112 }

    三、后记

      如果大家觉得不错,后期我会把数据解码的部分代码贴出来的。

    不忘初心,不忘本谋
  • 相关阅读:
    layui的table中日期格式转换
    动态数据网站
    卷积的微分以及积分性质
    傅里叶变换时域积分性质
    矩阵导数的一些笔记
    3层模式下长时间调用的进度条提示方案
    有限区域内的孤立点(极点,有限阶0点)数量有限。
    关于复变函数积分--原函数法
    android 获取文本框回车输入
    企业网络搭建
  • 原文地址:https://www.cnblogs.com/inverseEntropy/p/13808689.html
Copyright © 2011-2022 走看看