package jelly.command.coder.util;
import jelly.command.coder.exception.CmdCodecException;
import com.google.common.primitives.Ints;
import com.google.common.primitives.Longs;
import com.google.common.primitives.Shorts;
import com.sun.org.apache.xerces.internal.impl.dv.util.HexBin;
import org.apache.commons.lang3.ArrayUtils;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
public class CoderUtil {
public static void main(String[] args) throws Exception {
String pattern = "h2,h4,s,h4,i";
System.out.println(pattern);
String value = "621E,0000FEB1,29,FFFFFFFF,21";
System.out.println(value);
String encode = HexBin.encode(encode(pattern, value, false));
System.out.println(encode);
System.out.println(String.join(",",decode(pattern,HexBin.decode(encode),false)));
}
public static List<String> getSrcCode(byte[] bytes, String pattern) throws CmdCodecException {
pattern = pattern.replace("i", "i4")
.replace("s", "s2")
.replace("f", "f4")
.replace("l", "l8");
boolean hasBit = pattern.contains("b");
byte[] bits = BitUtils.bytesToBits(bytes);
ByteBuffer bytesBuf = ByteBuffer.wrap(bytes);
bytesBuf.position(0);
ByteBuffer bitsBuf = ByteBuffer.wrap(bits);
bitsBuf.position(0);
List<String> srcCodeList = new ArrayList<>();
String[] pa = pattern.split(",");
for (String s : pa) {
String type = s.substring(0, 1);
int len = Integer.parseInt(s.substring(1));
byte[] bytesTemp;
len = hasBit && !type.equals("b") ? len * 8 : len;
bytesTemp = new byte[len];
if (hasBit) {
bitsBuf.get(bytesTemp, 0, len);
} else {
bytesBuf.get(bytesTemp, 0, len);
}
switch (type) {
case "i":
case "s":
case "l":
case "f":
case "h":
srcCodeList.add(HexBin.encode(hasBit ? BitUtils.bitsToBytes(bytesTemp) : bytesTemp));
break;
case "b":
StringBuilder sb = new StringBuilder();
for (byte b : bytesTemp) sb.append(b);
srcCodeList.add(sb.toString());
break;
default:
throw new CmdCodecException("not support this type : " + type);
}
}
return srcCodeList;
}
/**
* @param pattern 字节数组的属性格式
* 例如:i,s,l,h4,b8,其中h和b后面需要指定字节长度
* i:表示4个字节的int
* s:表示2个字节的short,
* l:表示8个字节的long,
* h4:表示4个字节的16进制,
* b8:表示8个比特
* @param value 各属性的标示值,用“,”分割。例如:"2,3,4,A1B1C1D1,00001111"
* @return 组合后的字节数组
* @throws CmdCodecException 不支持类型
*/
public static byte[] encode(String pattern, String value, boolean isLittleEndian) throws CmdCodecException {
pattern = pattern.replace("i", "i4")
.replace("s", "s2")
.replace("f", "f4")
.replace("l", "l8");
String[] parArr = pattern.split(",");
String[] vaArr = value.split(",");
boolean hasBit = pattern.contains("b");
List<byte[]> bytesList = new ArrayList<>();
for (int i = 0; i < parArr.length; i++) {
String type = parArr[i].substring(0, 1);
String num = parArr[i].substring(1);
int len = Integer.parseInt(num);
String strValue = vaArr[i];
byte[] bytes;
switch (type) {
case "i":
bytes = Ints.toByteArray(Integer.parseInt(strValue));
if (isLittleEndian) ArrayUtils.reverse(bytes);
bytesList.add(hasBit ? BitUtils.bytesToBits(bytes) : bytes);
break;
case "s":
bytes = Shorts.toByteArray(Short.parseShort(strValue));
if (isLittleEndian) ArrayUtils.reverse(bytes);
bytesList.add(hasBit ? BitUtils.bytesToBits(bytes) : bytes);
break;
case "f":
float[] floats = {Float.parseFloat(strValue)};
bytes = ByteUtils.floatArrToByteArr(floats);
if (isLittleEndian) ArrayUtils.reverse(bytes);
bytesList.add(hasBit ? BitUtils.bytesToBits(bytes) : bytes);
break;
case "l":
bytes = Longs.toByteArray(Long.parseLong(strValue));
if (isLittleEndian) ArrayUtils.reverse(bytes);
bytesList.add(hasBit ? BitUtils.bytesToBits(bytes) : bytes);
break;
case "h":
bytes = HexBin.decode(strValue);
byte[] bytes1 = new byte[len];
System.arraycopy(bytes, 0, bytes1, len - bytes.length, bytes.length);
if (isLittleEndian) ArrayUtils.reverse(bytes1);
bytesList.add(hasBit ? BitUtils.bytesToBits(bytes1) : bytes1);
break;
case "b":
bytes = new byte[strValue.length()];
for (int k = 0; k < strValue.length(); k++) {
bytes[k] = Byte.parseByte(String.valueOf(strValue.charAt(k)));
}
bytes1 = new byte[len];
System.arraycopy(bytes, 0, bytes1, len - bytes.length, bytes.length);
bytesList.add(bytes);
break;
default:
throw new CmdCodecException("not support this type : " + type);
}
}
int len = 0;
for (byte[] bytes : bytesList) {
len += bytes.length;
}
ByteBuffer buffer = ByteBuffer.allocate(len);
for (byte[] bytes : bytesList) {
buffer.put(bytes);
}
return hasBit ? BitUtils.bitsToBytes(buffer.array()) : buffer.array();
}
public static String[] decode(String pattern, byte[] bytes, boolean isLittleEndian) throws CmdCodecException {
pattern = pattern.replace("i", "i4")
.replace("s", "s2")
.replace("f", "f4")
.replace("l", "l8");
boolean hasBit = pattern.contains("b");
byte[] bits = BitUtils.bytesToBits(bytes);
ByteBuffer bytesBuf = ByteBuffer.wrap(bytes);
bytesBuf.position(0);
ByteBuffer bitsBuf = ByteBuffer.wrap(bits);
bitsBuf.position(0);
String[] parArr = pattern.split(",");
String[] resultArr = new String[parArr.length];
for (int i = 0; i < parArr.length; i++) {
String s = parArr[i];
String type = s.substring(0, 1);
int len = Integer.parseInt(s.substring(1));
byte[] bytesTemp;
len = hasBit && !type.equals("b") ? len * 8 : len;
bytesTemp = new byte[len];
if (hasBit) {
bitsBuf.get(bytesTemp, 0, len);
} else {
bytesBuf.get(bytesTemp, 0, len);
}
byte[] tmp = hasBit ? BitUtils.bitsToBytes(bytesTemp) : bytesTemp;
if (isLittleEndian){
ArrayUtils.reverse(tmp);
}
switch (type) {
case "i":
resultArr[i] = String.valueOf(Ints.fromByteArray(tmp));
break;
case "s":
resultArr[i] = String.valueOf(Shorts.fromByteArray(tmp));
break;
case "l":
resultArr[i] = String.valueOf(Longs.fromByteArray(tmp));
break;
case "f":
resultArr[i] = String.valueOf(ByteUtils.byteArrToFloatArr(tmp)[0]);
break;
case "h":
resultArr[i] = HexBin.encode(tmp);
break;
case "b":
StringBuilder sb = new StringBuilder();
for (byte b : bytesTemp) sb.append(b);
resultArr[i] = sb.toString();
break;
default:
throw new CmdCodecException("not support this type : " + type);
}
}
return resultArr;
}
}
相关工具类
package jelly.command.coder.util;
import com.google.common.primitives.Ints;
import com.sun.org.apache.xerces.internal.impl.dv.util.HexBin;
import java.util.Arrays;
/**
* @Date 2020/12/26 17:08
* @Version 1.0
* @Description
*/
public class BitUtils {
public static void main(String[] args) {
System.out.println(Arrays.toString(hexStrToBits("0013")));
System.out.println(bitStrToHex("00000010011"));
}
public static byte bitStrToByte(String bitStr) {
int re, len;
if (bitStr == null) {
return 0;
}
len = bitStr.length();
if (len != 4 && len != 8) {
return 0;
}
if (len == 8) {//8 bit 处理
if (bitStr.charAt(0) == '0') {
re = Integer.parseInt(bitStr, 2);
} else {//负数
re = Integer.parseInt(bitStr, 2) - 256;
}
} else { //4 bit 处理
re = Integer.parseInt(bitStr, 2);
}
return (byte) re;
}
public static String byteToBitStr(byte by) {
return ""
+ (byte) ((by >> 7) & 0x1) + (byte) ((by >> 6) & 0x1)
+ (byte) ((by >> 5) & 0x1) + (byte) ((by >> 4) & 0x1)
+ (byte) ((by >> 3) & 0x1) + (byte) ((by >> 2) & 0x1)
+ (byte) ((by >> 1) & 0x1) + (byte) ((by) & 0x1);
}
public static byte[] byteToBitByByteArr(byte by) {
byte[] bits = new byte[8];
for (int i = 7; i >= 0; i--) {
bits[i] = (byte) (by & 1);
by = (byte) (by >> 1);
}
return bits;
}
public static byte[] bitsToBytes(byte[] bits) {
byte[] temp;
if (bits.length < 8) {
temp = new byte[8];
System.arraycopy(bits, 0, temp, 8 - bits.length, bits.length);
} else {
temp = bits;
}
byte[] bytes = new byte[temp.length / 8];
StringBuilder sb = new StringBuilder();
for (int i = 0; i < temp.length; i++) {
sb.append(temp[i]);
if (sb.length() == 8) {
bytes[i / 8] = bitStrToByte(sb.toString());
sb.delete(0, 8);
}
}
return bytes;
}
public static byte[] bitsToBytes(String bits) {
char[] chars = bits.toCharArray();
byte[] bytes = new byte[chars.length];
for (int i = 0; i < chars.length; i++) {
bytes[i] = Byte.parseByte(String.valueOf(chars[i]));
}
return bitsToBytes(bytes);
}
/**
* byte to bit array by Boolean array
*
* @param by
* @return
*/
public static boolean[] byteToBitByBooleanArr(byte by) {
boolean[] bits = new boolean[8];
for (int i = 7; i >= 0; i--) {
bits[i] = (by & 1) == 1;
by = (byte) (by >> 1);
}
return bits;
}
/**
* 字节数组转换成以字节表示为比特的数组
*
* @param bytes
* @return
*/
public static byte[] bytesToBits(byte[] bytes) {
byte[] temp = new byte[bytes.length * 8];
for (int i = 0; i < bytes.length; i++) {
byte[] bits = byteToBitByByteArr(bytes[i]);
System.arraycopy(bits, 0, temp, i * 8, 8);
}
return temp;
}
public static byte[] hexStrToBits(String hex) {
if (hex.contains("H")) {
hex = hex.replace("H", "");
}
return bytesToBits(ByteUtils.hexToBytes(hex));
}
public static String hexStrToBits(String hex, int len) {
if (hex.contains("H")) {
hex = hex.replace("H", "");
}
byte[] bits = bytesToBits(ByteUtils.hexToBytes(hex));
int hexLen = hex.length() * 4;
StringBuilder sb = new StringBuilder();
if (hexLen >= len) { //取后len位
for (int i = bits.length - len; i < bits.length; i++) {
sb.append(bits[i]);
}
} else {//前面填充0
for (int i = 0; i < len - hexLen; i++) {
sb.append("0");
}
for (byte bit : bits) {
sb.append(bit);
}
}
return sb.toString();
}
public static String bitStrToHex(String param) {
//前面需要填充0的个数
int remain = param.length() % 8;
int num = 0;
if (remain > 0) {
num = 8 - remain;
}
String bits = param;
if (num > 0) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < num; i++) {
sb.append(0);
}
sb.append(param);
bits = sb.toString();
}
return HexBin.encode(bitsToBytes(bits));
}
/**
* 截取后len位bit
*
* @param value
* @param len
* @return
*/
public static String intToBits(int value, int len) {
StringBuilder sb = new StringBuilder();
byte[] bits = bytesToBits(Ints.toByteArray(value));
for (int i = bits.length - len; i < bits.length; i++) {
sb.append(bits[i]);
}
return sb.toString();
}
}
package jelly.command.coder.util;
import com.google.common.primitives.Ints;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
/**
* @Date 2020/12/23 10:55
* @Version 1.0
* @Description
*/
public class ByteUtils {
private static final char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
public static void main(String[] args) {
System.out.println(revertHex("ABCDDEFH"));
}
public static byte[] hexToBytes(String hex) {
if (hex == null || hex.length() == 0) {
return null;
}
char[] chars = hex.toCharArray();
byte[] bytes = new byte[chars.length / 2];
for (int i = 0; i < bytes.length; i++) {
bytes[i] = (byte) Integer.parseInt("" + chars[i * 2] + chars[i * 2 + 1], 16);
}
return bytes;
}
public static String bytesToHex(byte[] bytes) {
if (bytes == null || bytes.length == 0) {
return null;
}
StringBuilder hex = new StringBuilder();
for (byte b : bytes) {
hex.append(hexDigits[(b >> 4) & 0x0F]);
hex.append(hexDigits[b & 0x0F]);
}
return hex.toString();
}
/**
* 反转
*
* @param source
* @param begin
* @param length
* @return
*/
public static byte[] arraySliceAndReverse(
byte[] source,
int begin,
int length) {
byte[] tempArr = new byte[source.length];
System.arraycopy(source, 0, tempArr, 0, source.length);
byte temp;
for (int i = 0; i < (source.length - length) / 2; i++) {
temp = tempArr[begin + i];
tempArr[begin + i] = tempArr[source.length - i - 1];
tempArr[source.length - i - 1] = temp;
}
return tempArr;
}
/**
* 已测试
*
* @param bytes
* @return
*/
public static int bytesToInt(byte[] bytes) {
byte[] temp = new byte[Integer.BYTES];
if (bytes.length < 4) {
System.arraycopy(bytes, 0, temp, temp.length - bytes.length, bytes.length);
} else if (bytes.length > 4) {
System.arraycopy(bytes, bytes.length - 4, temp, 0, Integer.BYTES);
}
return Ints.fromByteArray(temp);
}
public static String bytesToString(byte[] bytes, char placeholder) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
if (b == (byte) placeholder) {
break;
}
sb.append((char) b);
}
return sb.toString();
}
/**
* String -> bytes array
*
* @param param 原字符串
* @param length bytes 数组长度
* @param placeholder 数组空余位置填充
* @return 字节数组
*/
public static byte[] stringToBytes(String param, int length, char placeholder) {
byte[] rawContent = new byte[length];
char[] array = param.toCharArray();
int len = Math.min(array.length, length);
for (int i = 0; i < len; i++) {
rawContent[i] = (byte) array[i];
}
for (int i = array.length; i < length; i++) {
rawContent[i] = (byte) (placeholder);
}
return rawContent;
}
public static String revertHex(String hex) {
StringBuilder sb = new StringBuilder();
for (int i = hex.length() - 1; i >= 0; i -= 2) {
sb.append(hex, i - 1, i + 1);
}
return sb.toString();
}
public static float[] byteArrToFloatArr(byte[] bytes) {
ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
FloatBuffer floatBuffer = byteBuffer.asFloatBuffer();
float[] aFloat = new float[floatBuffer.limit()];
floatBuffer.get(aFloat);
return aFloat;
}
public static byte[] floatArrToByteArr(float[] floats) {
ByteBuffer buffer = ByteBuffer.allocate(floats.length * 4);
FloatBuffer floatBuffer = buffer.asFloatBuffer();
floatBuffer.put(floats);
return buffer.array();
}
}