2023-03-04 16:29:55 +08:00
|
|
|
|
package com.jsowell.common.util;
|
|
|
|
|
|
|
|
|
|
|
|
import com.google.common.primitives.Bytes;
|
2024-02-20 16:05:54 +08:00
|
|
|
|
import com.jsowell.common.constant.Constants;
|
2024-08-29 15:10:41 +08:00
|
|
|
|
import lombok.extern.slf4j.Slf4j;
|
2023-03-04 16:29:55 +08:00
|
|
|
|
|
2024-03-18 16:39:37 +08:00
|
|
|
|
import javax.xml.bind.DatatypeConverter;
|
2023-03-04 16:29:55 +08:00
|
|
|
|
import java.io.UnsupportedEncodingException;
|
|
|
|
|
|
import java.math.BigInteger;
|
2024-08-26 16:53:52 +08:00
|
|
|
|
import java.nio.ByteBuffer;
|
2023-03-04 16:29:55 +08:00
|
|
|
|
import java.time.LocalDateTime;
|
|
|
|
|
|
import java.util.Date;
|
|
|
|
|
|
import java.util.Stack;
|
|
|
|
|
|
|
2024-08-29 15:10:41 +08:00
|
|
|
|
@Slf4j
|
2023-03-04 16:29:55 +08:00
|
|
|
|
public class BytesUtil {
|
|
|
|
|
|
|
|
|
|
|
|
static final long fx = 0xffl;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 将int数值转换为占两个字节的byte数组,本方法适用于(高位在前,低位在后)的顺序。
|
2024-08-26 16:53:52 +08:00
|
|
|
|
* 大端模式
|
2023-03-04 16:29:55 +08:00
|
|
|
|
*/
|
|
|
|
|
|
public static byte[] intToBytes(int value) {
|
|
|
|
|
|
//limit 传入2
|
|
|
|
|
|
return intToBytes(value, 2);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-08-26 16:53:52 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 将int转换byte 大端模式
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param value int值
|
|
|
|
|
|
* @param limit 保留长度
|
|
|
|
|
|
* @return
|
|
|
|
|
|
*/
|
2023-03-04 16:29:55 +08:00
|
|
|
|
public static byte[] intToBytes(int value, int limit) {
|
|
|
|
|
|
byte[] src = new byte[limit];
|
|
|
|
|
|
for (int i = 0; i < limit; i++) {
|
|
|
|
|
|
int x = 8 * (limit - i - 1);
|
|
|
|
|
|
if (x == 0) {
|
|
|
|
|
|
src[i] = (byte) (value & 0xFF);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
src[i] = (byte) ((value >> x) & 0xFF);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return src;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-08-26 16:53:52 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 将int转换为byte数组,并采用小端模式。
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param value 需要转换的整型值
|
|
|
|
|
|
* @return 转换后的字节数组
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static byte[] intToBytesLittleEndian(int value) {
|
|
|
|
|
|
ByteBuffer buffer = ByteBuffer.allocate(2); // 分配4字节的空间
|
|
|
|
|
|
buffer.order(java.nio.ByteOrder.LITTLE_ENDIAN); // 设置为小端模式
|
|
|
|
|
|
buffer.putInt(value); // 将整数放入缓冲区
|
|
|
|
|
|
return buffer.array(); // 返回字节数组
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 将int转为byte 小端模式
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param value int值
|
|
|
|
|
|
* @return
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static byte[] intToBytesLittle(int value) {
|
|
|
|
|
|
//limit 传入2
|
|
|
|
|
|
return intToBytesLittle(value, 2);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 将int转换byte 小端模式
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param value int值
|
|
|
|
|
|
* @param limit 保留长度
|
|
|
|
|
|
* @return
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static byte[] intToBytesLittle(int value, int limit) {
|
|
|
|
|
|
// 参数检查,确保limit非负且不超过int类型的字节长度
|
|
|
|
|
|
if (limit < 0 || limit > 4) {
|
|
|
|
|
|
throw new IllegalArgumentException("Limit must be between 0 and 4 inclusive.");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
byte[] src = new byte[limit];
|
|
|
|
|
|
for (int i = 0; i < limit; i++) {
|
|
|
|
|
|
int x = 8 * i;
|
|
|
|
|
|
// 直接进行位移操作,无需特殊判断x是否为0
|
|
|
|
|
|
src[i] = (byte) ((value >> x) & 0xFF);
|
|
|
|
|
|
}
|
|
|
|
|
|
return src;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-03-04 16:29:55 +08:00
|
|
|
|
public static int bytesToInt(byte[] src) {
|
|
|
|
|
|
return bytesToInt(src, 0);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* byte数组中取int数值,本方法适用于(低位在后,高位在前)的顺序。
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static int bytesToInt(byte[] src, int offset) {
|
|
|
|
|
|
if (src == null) {
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
while (src.length > 0 && src[0] == 0x00) {
|
|
|
|
|
|
src = BytesUtil.copyBytes(src, 1, src.length - 1);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (src.length == 0) {
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
int len = src.length;
|
|
|
|
|
|
if (len == 0) {
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
int value = 0;
|
|
|
|
|
|
for (int i = 0; i < len; i++) {
|
|
|
|
|
|
if (i == (len - 1)) {
|
|
|
|
|
|
value = value | ((src[i] & 0xFF));
|
|
|
|
|
|
}
|
|
|
|
|
|
value = value | ((src[i] & 0xFF) << (8 * (len - i - 1)));
|
|
|
|
|
|
}
|
|
|
|
|
|
return value;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* long转字节,大端模式
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param number
|
|
|
|
|
|
* @return
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static byte[] long2Byte(long number) {
|
|
|
|
|
|
long temp = number;
|
|
|
|
|
|
byte[] b = new byte[8];
|
|
|
|
|
|
for (int i = (b.length - 1); i >= 0; i--) {
|
|
|
|
|
|
b[i] = new Long(temp & 0xff).byteValue();//
|
|
|
|
|
|
//将最低位保存在最低位
|
|
|
|
|
|
temp = temp >> 8;// 向右移8位
|
|
|
|
|
|
}
|
|
|
|
|
|
return b;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 字节转long 大端模式
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param b
|
|
|
|
|
|
* @return
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static long byte2Long(byte[] b) {
|
|
|
|
|
|
long s = 0;
|
|
|
|
|
|
long s0 = b[7] & 0xff;
|
|
|
|
|
|
long s1 = b[6] & 0xff;
|
|
|
|
|
|
long s2 = b[5] & 0xff;
|
|
|
|
|
|
long s3 = b[4] & 0xff;
|
|
|
|
|
|
long s4 = b[3] & 0xff;
|
|
|
|
|
|
long s5 = b[2] & 0xff;
|
|
|
|
|
|
long s6 = b[1] & 0xff;
|
|
|
|
|
|
long s7 = b[0] & 0xff;
|
|
|
|
|
|
|
|
|
|
|
|
// s0不变
|
|
|
|
|
|
s1 <<= 8;
|
|
|
|
|
|
s2 <<= 16;
|
|
|
|
|
|
s3 <<= 24;
|
|
|
|
|
|
s4 <<= 8 * 4;
|
|
|
|
|
|
s5 <<= 8 * 5;
|
|
|
|
|
|
s6 <<= 8 * 6;
|
|
|
|
|
|
s7 <<= 8 * 7;
|
|
|
|
|
|
s = s0 | s1 | s2 | s3 | s4 | s5 | s6 | s7;
|
|
|
|
|
|
return s;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 从一个byte数组中拷贝一部分出来
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param oriBytes
|
|
|
|
|
|
* @param startIndex
|
|
|
|
|
|
* @param length
|
|
|
|
|
|
* @return
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static byte[] copyBytes(byte[] oriBytes, int startIndex, int length) {
|
|
|
|
|
|
int endIndex = startIndex + length;
|
|
|
|
|
|
byte[] bts = new byte[length];
|
|
|
|
|
|
int index = 0;
|
|
|
|
|
|
for (int i = 0; i < oriBytes.length; i++) {
|
|
|
|
|
|
if (i >= startIndex && i < endIndex) {
|
|
|
|
|
|
bts[index] = oriBytes[i];
|
|
|
|
|
|
index++;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return bts;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 将byte[]转为各种进制的字符串
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param bytes byte[]
|
|
|
|
|
|
* @param radix 基数可以转换进制的范围,从Character.MIN_RADIX到Character.MAX_RADIX,超出范围后变为10进制
|
|
|
|
|
|
* @return 转换后的字符串
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static String binary(byte[] bytes, int radix) {
|
|
|
|
|
|
return new BigInteger(1, bytes).toString(radix);// 这里的1代表正数
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-03-18 16:39:37 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 将byte[]转为十六进制的字符串
|
2024-08-26 16:53:52 +08:00
|
|
|
|
* 可以与hexStringToByteArray互转
|
2024-03-18 16:39:37 +08:00
|
|
|
|
* @param bytes byte[]
|
|
|
|
|
|
* @return 转换后的字符串
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static String printHexBinary(byte[] bytes) {
|
|
|
|
|
|
return DatatypeConverter.printHexBinary(bytes);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-03-04 16:29:55 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @函数功能: BCD码转为10进制串(阿拉伯数据)
|
|
|
|
|
|
* @输入参数: BCD码
|
|
|
|
|
|
* @输出结果: 10进制串
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static String bcd2Str(byte[] bytes) {
|
|
|
|
|
|
StringBuffer temp = new StringBuffer(bytes.length * 2);
|
|
|
|
|
|
for (int i = 0; i < bytes.length; i++) {
|
|
|
|
|
|
temp.append((byte) ((bytes[i] & 0xf0) >>> 4));
|
|
|
|
|
|
temp.append((byte) (bytes[i] & 0x0f));
|
|
|
|
|
|
}
|
|
|
|
|
|
return temp.toString();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static String bcd2StrContainA(byte[] bytes) {
|
|
|
|
|
|
char temp[] = new char[bytes.length * 2], val;
|
|
|
|
|
|
for (int i = 0; i < bytes.length; i++) {
|
|
|
|
|
|
val = (char) (((bytes[i] & 0xf0) >> 4) & 0x0f);
|
|
|
|
|
|
temp[i * 2] = (char) (val > 9 ? val + 'A' - 10 : val + '0');
|
|
|
|
|
|
val = (char) (bytes[i] & 0x0f);
|
|
|
|
|
|
temp[i * 2 + 1] = (char) (val > 9 ? val + 'A' - 10 : val + '0');
|
|
|
|
|
|
}
|
|
|
|
|
|
return new String(temp);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @函数功能: BCD码转为10进制串(阿拉伯数据) 小端模式
|
|
|
|
|
|
* @输入参数: BCD码
|
|
|
|
|
|
* @输出结果: 10进制串
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static String bcd2StrLittle(byte[] bytes) {
|
|
|
|
|
|
Stack<String> strings = new Stack<>();
|
|
|
|
|
|
String temp = bcd2Str(bytes);
|
|
|
|
|
|
for (int i = 0; i < temp.length(); i = i + 2) {
|
|
|
|
|
|
strings.push(temp.substring(i, i + 2));
|
|
|
|
|
|
}
|
|
|
|
|
|
StringBuilder stringBuilder = new StringBuilder();
|
|
|
|
|
|
while (!strings.isEmpty()) {
|
|
|
|
|
|
stringBuilder.append(strings.pop());
|
|
|
|
|
|
}
|
|
|
|
|
|
return stringBuilder.toString();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @函数功能: BCD码转为10进制串(阿拉伯数据) 小端模式
|
|
|
|
|
|
* @输入参数: BCD码
|
|
|
|
|
|
* @输出结果: 10进制串
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static String bcd2StrLittleContainA(byte[] bytes) {
|
|
|
|
|
|
Stack<String> strings = new Stack<>();
|
|
|
|
|
|
String temp = bcd2StrContainA(bytes);
|
|
|
|
|
|
for (int i = 0; i < temp.length(); i = i + 2) {
|
|
|
|
|
|
strings.push(temp.substring(i, i + 2));
|
|
|
|
|
|
}
|
|
|
|
|
|
StringBuilder stringBuilder = new StringBuilder();
|
|
|
|
|
|
while (!strings.isEmpty()) {
|
|
|
|
|
|
stringBuilder.append(strings.pop());
|
|
|
|
|
|
}
|
|
|
|
|
|
return stringBuilder.toString();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @函数功能: 10进制串转为BCD码
|
|
|
|
|
|
* @输入参数: 10进制串
|
|
|
|
|
|
* @输出结果: BCD码
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static byte[] str2Bcd(String asc) {
|
|
|
|
|
|
if (asc == null) {
|
|
|
|
|
|
asc = "";
|
|
|
|
|
|
}
|
|
|
|
|
|
int len = asc.length();
|
|
|
|
|
|
int mod = len % 2;
|
|
|
|
|
|
if (mod != 0) {
|
|
|
|
|
|
asc = "0" + asc;
|
|
|
|
|
|
len = asc.length();
|
|
|
|
|
|
}
|
|
|
|
|
|
byte abt[] = new byte[len];
|
|
|
|
|
|
if (len >= 2) {
|
|
|
|
|
|
len = len / 2;
|
|
|
|
|
|
}
|
|
|
|
|
|
byte bbt[] = new byte[len];
|
|
|
|
|
|
abt = asc.getBytes();
|
|
|
|
|
|
int j, k;
|
|
|
|
|
|
for (int p = 0; p < asc.length() / 2; p++) {
|
|
|
|
|
|
if ((abt[2 * p] >= '0') && (abt[2 * p] <= '9')) {
|
|
|
|
|
|
j = abt[2 * p] - '0';
|
|
|
|
|
|
} else if ((abt[2 * p] >= 'a') && (abt[2 * p] <= 'z')) {
|
|
|
|
|
|
j = abt[2 * p] - 'a' + 0x0a;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
j = abt[2 * p] - 'A' + 0x0a;
|
|
|
|
|
|
}
|
|
|
|
|
|
if ((abt[2 * p + 1] >= '0') && (abt[2 * p + 1] <= '9')) {
|
|
|
|
|
|
k = abt[2 * p + 1] - '0';
|
|
|
|
|
|
} else if ((abt[2 * p + 1] >= 'a') && (abt[2 * p + 1] <= 'z')) {
|
|
|
|
|
|
k = abt[2 * p + 1] - 'a' + 0x0a;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
k = abt[2 * p + 1] - 'A' + 0x0a;
|
|
|
|
|
|
}
|
|
|
|
|
|
int a = (j << 4) + k;
|
|
|
|
|
|
byte b = (byte) a;
|
|
|
|
|
|
bbt[p] = b;
|
|
|
|
|
|
}
|
|
|
|
|
|
return bbt;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @函数功能: 10进制串转为BCD码
|
|
|
|
|
|
* @输入参数: 10进制串
|
|
|
|
|
|
* @输出结果: BCD码
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static byte[] str2BcdLittle(String asc) {
|
|
|
|
|
|
byte[] temp = str2Bcd(asc);
|
|
|
|
|
|
return revert(temp);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2024-08-03 16:02:50 +08:00
|
|
|
|
public static void main(String[] args) {
|
|
|
|
|
|
byte[] length = new byte[] {0x09, 0x00};
|
|
|
|
|
|
int i = BytesUtil.bytesToIntLittle(length);
|
|
|
|
|
|
System.out.println(i);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-03-04 16:29:55 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* byte数组中取int数值,本方法适用于(低位在前,高位在后 )的顺序。小端模式
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static int bytesToIntLittle(byte[] src) {
|
|
|
|
|
|
if (src == null) {
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
int len = src.length;
|
|
|
|
|
|
if (len == 0) {
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
int value = 0;
|
|
|
|
|
|
for (int i = 0; i < len; i++) {
|
|
|
|
|
|
value = value | ((src[i] & 0xFF) << (8 * i));
|
|
|
|
|
|
}
|
|
|
|
|
|
return value;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* long转字节,小端模式
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param number
|
|
|
|
|
|
* @param limit 保留字节位
|
|
|
|
|
|
* @return
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static byte[] long2ByteLittle(long number, int limit) {
|
|
|
|
|
|
long temp = number;
|
|
|
|
|
|
byte[] b = new byte[limit];
|
|
|
|
|
|
for (int i = 0; i < b.length; i++) {
|
|
|
|
|
|
b[i] = new Long(temp & 0xff).byteValue();//
|
|
|
|
|
|
//将最低位保存在最前面
|
|
|
|
|
|
temp = temp >> 8;// 向右移8位
|
|
|
|
|
|
}
|
|
|
|
|
|
return b;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 字节转long 小端模式
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param src
|
|
|
|
|
|
* @return
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static long byte2LongLittle(byte[] src) {
|
|
|
|
|
|
long s = 0;
|
|
|
|
|
|
for (int i = 0; i < src.length; i++) {
|
|
|
|
|
|
//防止转为int
|
|
|
|
|
|
long si = src[i] & 0xFF;
|
|
|
|
|
|
si = si << (8 * i);
|
|
|
|
|
|
s = s | si;
|
|
|
|
|
|
}
|
|
|
|
|
|
return s;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 使用字节数组替换目标数组从指定位置开始替换字节
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param target 被替换的数组
|
|
|
|
|
|
* @param startIndex 开始位置
|
|
|
|
|
|
* @param replace 用于替换的数组
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static void replaceBytes(byte[] target, int startIndex, byte[] replace) {
|
|
|
|
|
|
// 暂时由外界保证不会出数组越界的异常
|
|
|
|
|
|
for (int i = 0; i < replace.length; i++) {
|
|
|
|
|
|
int targetIndex = startIndex + i;
|
|
|
|
|
|
target[targetIndex] = replace[i];
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 创建数组
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param bytes 用于替换的数组
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static byte[] createByteArray(byte... bytes) {
|
|
|
|
|
|
byte[] temp = new byte[bytes.length];
|
|
|
|
|
|
for (int i = 0; i < bytes.length; i++) {
|
|
|
|
|
|
temp[i] = bytes[i];
|
|
|
|
|
|
}
|
|
|
|
|
|
return temp;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static byte[] rightPadBytes(byte[] target, int len, byte b) {
|
|
|
|
|
|
int length = target.length;
|
|
|
|
|
|
if (len <= length) {
|
|
|
|
|
|
return target;
|
|
|
|
|
|
}
|
|
|
|
|
|
int addedLen = len - length;
|
|
|
|
|
|
byte[] added = new byte[addedLen];
|
|
|
|
|
|
for (int i = 0; i < addedLen; i++) {
|
|
|
|
|
|
added[i] = b;
|
|
|
|
|
|
}
|
|
|
|
|
|
return Bytes.concat(target, added);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static byte[] rightPadBytes(String targetStr, int len, byte b) {
|
|
|
|
|
|
if (targetStr == null) {
|
|
|
|
|
|
targetStr = "";
|
|
|
|
|
|
}
|
|
|
|
|
|
byte[] target = targetStr.getBytes();
|
|
|
|
|
|
return rightPadBytes(target, len, b);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-07-08 11:06:11 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* ASCII转字符串 小端模式
|
|
|
|
|
|
* @param ascs
|
|
|
|
|
|
* @return
|
|
|
|
|
|
*/
|
2023-03-04 16:29:55 +08:00
|
|
|
|
public static String ascii2StrLittle(byte[] ascs) {
|
|
|
|
|
|
byte[] data = revert(ascs);
|
|
|
|
|
|
String asciiStr = null;
|
|
|
|
|
|
try {
|
|
|
|
|
|
asciiStr = new String(data, "ISO8859-1");
|
|
|
|
|
|
} catch (UnsupportedEncodingException e) {
|
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
|
}
|
|
|
|
|
|
return asciiStr;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-07-08 11:06:11 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* ASCII转字符串
|
|
|
|
|
|
* @param ascs
|
|
|
|
|
|
* @return
|
|
|
|
|
|
*/
|
2023-03-04 16:29:55 +08:00
|
|
|
|
public static String ascii2Str(byte[] ascs) {
|
|
|
|
|
|
byte[] data = ascs;
|
|
|
|
|
|
String asciiStr = null;
|
|
|
|
|
|
try {
|
|
|
|
|
|
asciiStr = new String(data, "ISO8859-1");
|
|
|
|
|
|
} catch (UnsupportedEncodingException e) {
|
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
|
}
|
|
|
|
|
|
return asciiStr;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-07-08 11:06:11 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 字符串转ASCII 小端模式
|
|
|
|
|
|
* @param str
|
|
|
|
|
|
* @return
|
|
|
|
|
|
*/
|
2023-03-04 16:29:55 +08:00
|
|
|
|
public static byte[] str2AscLittle(String str) {
|
|
|
|
|
|
return revert(str2Asc(str));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-07-08 11:06:11 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 字符串转ASCII
|
|
|
|
|
|
* @param str
|
|
|
|
|
|
* @return
|
|
|
|
|
|
*/
|
2023-03-04 16:29:55 +08:00
|
|
|
|
public static byte[] str2Asc(String str) {
|
|
|
|
|
|
byte[] bytes = null;
|
|
|
|
|
|
try {
|
|
|
|
|
|
bytes = str.getBytes("ISO8859-1");
|
|
|
|
|
|
} catch (UnsupportedEncodingException e) {
|
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
|
}
|
|
|
|
|
|
return bytes;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 反转byte数组
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param temp
|
|
|
|
|
|
* @return
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static byte[] revert(byte[] temp) {
|
|
|
|
|
|
byte[] ret = new byte[temp.length];
|
|
|
|
|
|
for (int i = 0; i < temp.length; i++) {
|
|
|
|
|
|
ret[temp.length - i - 1] = temp[i];
|
|
|
|
|
|
}
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* cp56time2a 格式转date格式
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static Date byteCp2Date(byte[] bytes) {
|
|
|
|
|
|
if (bytes == null || bytes.length != 7) {
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
int ms = bytesToIntLittle(copyBytes(bytes, 0, 2));
|
|
|
|
|
|
int min = bytesToIntLittle(copyBytes(bytes, 2, 1));
|
|
|
|
|
|
int hour = bytesToIntLittle(copyBytes(bytes, 3, 1));
|
|
|
|
|
|
int day = bytesToIntLittle(copyBytes(bytes, 4, 1));
|
|
|
|
|
|
int month = bytesToIntLittle(copyBytes(bytes, 5, 1));
|
|
|
|
|
|
int year = bytesToIntLittle(copyBytes(bytes, 6, 1));
|
|
|
|
|
|
if (month == 0 || day == 0 || year == 0) {
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
LocalDateTime localDateTime = LocalDateTime.of(year + 2000, month, day, hour, min, ms / 1000);
|
|
|
|
|
|
Date date = DateUtils.localDateTime2Date(localDateTime);
|
|
|
|
|
|
return date;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private static String hexStr = "0123456789ABCDEF";
|
|
|
|
|
|
private static String[] binaryArray = {
|
|
|
|
|
|
"0000", "0001", "0010", "0011",
|
|
|
|
|
|
"0100", "0101", "0110", "0111",
|
|
|
|
|
|
"1000", "1001", "1010", "1011",
|
|
|
|
|
|
"1100", "1101", "1110", "1111"
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @param bArray
|
|
|
|
|
|
* @return 二进制数组转换为二进制字符串 2-2
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static String bytes2BinStr(byte[] bArray) {
|
|
|
|
|
|
String outStr = "";
|
|
|
|
|
|
int pos = 0;
|
|
|
|
|
|
for (byte b : bArray) {
|
|
|
|
|
|
//高四位
|
|
|
|
|
|
pos = (b & 0xF0) >> 4;
|
|
|
|
|
|
outStr += binaryArray[pos];
|
|
|
|
|
|
//低四位
|
|
|
|
|
|
pos = b & 0x0F;
|
|
|
|
|
|
outStr += binaryArray[pos];
|
|
|
|
|
|
}
|
|
|
|
|
|
return outStr;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @param bytes
|
|
|
|
|
|
* @return 将二进制数组转换为十六进制字符串 2-16
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static String bin2HexStr(byte[] bytes) {
|
|
|
|
|
|
String result = "";
|
|
|
|
|
|
String hex = "";
|
|
|
|
|
|
for (byte aByte : bytes) {
|
|
|
|
|
|
//字节高4位
|
|
|
|
|
|
hex = String.valueOf(hexStr.charAt((aByte & 0xF0) >> 4));
|
|
|
|
|
|
//字节低4位
|
|
|
|
|
|
hex += String.valueOf(hexStr.charAt(aByte & 0x0F));
|
|
|
|
|
|
result += hex; //+" "
|
|
|
|
|
|
}
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @param hexString
|
|
|
|
|
|
* @return 将十六进制转换为二进制字节数组 16-2
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static byte[] hexStr2BinArr(String hexString) {
|
|
|
|
|
|
//hexString的长度对2取整,作为bytes的长度
|
|
|
|
|
|
int len = hexString.length() / 2;
|
|
|
|
|
|
byte[] bytes = new byte[len];
|
|
|
|
|
|
byte high = 0;//字节高四位
|
|
|
|
|
|
byte low = 0;//字节低四位
|
|
|
|
|
|
for (int i = 0; i < len; i++) {
|
|
|
|
|
|
//右移四位得到高位
|
|
|
|
|
|
high = (byte) ((hexStr.indexOf(hexString.charAt(2 * i))) << 4);
|
|
|
|
|
|
low = (byte) hexStr.indexOf(hexString.charAt(2 * i + 1));
|
|
|
|
|
|
bytes[i] = (byte) (high | low);//高地位做或运算
|
|
|
|
|
|
}
|
|
|
|
|
|
return bytes;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2024-05-17 17:07:19 +08:00
|
|
|
|
* 十六进制字符串 转 bytes数组
|
2023-03-04 16:29:55 +08:00
|
|
|
|
* @param src 16进制字符串
|
|
|
|
|
|
* @return 字节数组
|
|
|
|
|
|
* @Title hexString2Bytes
|
|
|
|
|
|
* @Description 16进制字符串转字节数组
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static byte[] hexString2Bytes(String src) {
|
2024-02-20 16:05:54 +08:00
|
|
|
|
if (src.startsWith(Constants.HEX_PREFIX)) {
|
|
|
|
|
|
src = StringUtils.replace(src, Constants.HEX_PREFIX, "");
|
|
|
|
|
|
}
|
2023-03-04 16:29:55 +08:00
|
|
|
|
int l = src.length() / 2;
|
|
|
|
|
|
byte[] ret = new byte[l];
|
|
|
|
|
|
for (int i = 0; i < l; i++) {
|
|
|
|
|
|
ret[i] = (byte) Integer.valueOf(src.substring(i * 2, i * 2 + 2), 16).byteValue();
|
|
|
|
|
|
}
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @param hexString
|
|
|
|
|
|
* @return 将十六进制转换为二进制字符串 16-2
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static String hexStr2BinStr(String hexString) {
|
|
|
|
|
|
return bytes2BinStr(hexStr2BinArr(hexString));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 校验数据长度是否达到要求,如果够长,就直接返回,如果不够,则在数据 后补0 直至到达该长度
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param msg byte类型数组
|
|
|
|
|
|
* @parm length 需要检验的数据长度(为实际字节数)
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static byte[] checkLengthAndBehindAppendZero(byte[] msg, int length) {
|
|
|
|
|
|
String s = BytesUtil.binary(msg, 16);
|
2024-05-23 16:41:20 +08:00
|
|
|
|
int msgLen = s.length();
|
2023-03-04 16:29:55 +08:00
|
|
|
|
if (msgLen < length) {
|
|
|
|
|
|
while (msgLen < length) {
|
|
|
|
|
|
StringBuffer sb = new StringBuffer();
|
|
|
|
|
|
// 后补零
|
|
|
|
|
|
sb.append(s).append("0");
|
|
|
|
|
|
s = sb.toString();
|
|
|
|
|
|
msgLen = s.length();
|
2024-05-23 16:41:20 +08:00
|
|
|
|
}
|
2023-03-04 16:29:55 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
return msg;
|
|
|
|
|
|
}
|
|
|
|
|
|
return BytesUtil.str2Bcd(s);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 校验数据长度是否达到要求,如果够长,就直接返回,如果不够,则在数据 前补0 直至到达该长度
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param msg byte类型数组
|
|
|
|
|
|
* @parm length 需要检验的数据长度(为实际字节数)
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static byte[] checkLengthAndFrontAppendZero(byte[] msg, int length) {
|
|
|
|
|
|
String s = BytesUtil.binary(msg, 16);
|
|
|
|
|
|
int msgLen = msg.length;
|
|
|
|
|
|
if (msgLen < length) {
|
|
|
|
|
|
while (msgLen < length) {
|
|
|
|
|
|
StringBuffer sb = new StringBuffer();
|
|
|
|
|
|
// 前补零
|
|
|
|
|
|
sb.append("0").append(s);
|
|
|
|
|
|
s = sb.toString();
|
|
|
|
|
|
msgLen = s.length();
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
return msg;
|
|
|
|
|
|
}
|
|
|
|
|
|
return BytesUtil.str2Bcd(s);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-05-23 16:41:20 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 确保byte数组长度至少为指定长度,不足则在末尾补充0。
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param bytes 原始byte数组
|
|
|
|
|
|
* @param length 指定的最小长度
|
|
|
|
|
|
* @return 补充0后确保长度至少为指定长度的byte数组
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static byte[] ensureLength(byte[] bytes, int length) {
|
|
|
|
|
|
if (bytes.length < length) {
|
|
|
|
|
|
// 创建一个新的byte数组,长度为指定长度,前面填充原数组的元素,后面补充0
|
|
|
|
|
|
byte[] newArray = new byte[length];
|
|
|
|
|
|
System.arraycopy(bytes, 0, newArray, 0, bytes.length);
|
|
|
|
|
|
return newArray;
|
|
|
|
|
|
}
|
|
|
|
|
|
// 如果原数组长度已经达到或超过指定长度,则直接返回原数组
|
|
|
|
|
|
return bytes;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 确保byte数组长度至少为指定长度,不足则在前面补充0。
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param bytes 原始byte数组
|
|
|
|
|
|
* @param length 指定的最小长度
|
|
|
|
|
|
* @return 补充0后确保长度至少为指定长度的byte数组,不足部分在前面补充
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static byte[] ensureLengthPrependZero(byte[] bytes, int length) {
|
|
|
|
|
|
if (bytes.length < length) {
|
|
|
|
|
|
// 创建一个新的byte数组,长度为指定长度,前面补充0,后面放置原数组的元素
|
|
|
|
|
|
byte[] newArray = new byte[length];
|
|
|
|
|
|
System.arraycopy(bytes, 0, newArray, length - bytes.length, bytes.length);
|
|
|
|
|
|
return newArray;
|
|
|
|
|
|
}
|
|
|
|
|
|
// 如果原数组长度已经达到或超过指定长度,则直接返回原数组
|
|
|
|
|
|
return bytes;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-03-04 16:29:55 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 将金额转换成BCD数组
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param bigDecimal
|
|
|
|
|
|
* @return
|
|
|
|
|
|
*/
|
2024-02-20 16:05:54 +08:00
|
|
|
|
// public static byte[] bigDecimal2Bcd(BigDecimal bigDecimal) {
|
|
|
|
|
|
// int i = Float.floatToIntBits(bigDecimal.floatValue());
|
|
|
|
|
|
// String hexString = Integer.toHexString(i);
|
|
|
|
|
|
// return hexString2Bytes(hexString);
|
|
|
|
|
|
//
|
|
|
|
|
|
// }
|
2023-03-04 16:29:55 +08:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* int 转 byte[]
|
|
|
|
|
|
* 小端
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param data
|
|
|
|
|
|
* @return
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static byte[] getIntBytes(int data) {
|
|
|
|
|
|
int length = 4;
|
|
|
|
|
|
byte[] bytes = new byte[length];
|
|
|
|
|
|
for (int i = 0; i < length; i++) {
|
|
|
|
|
|
bytes[i] = (byte) ((data >> (i * 8)) & fx);
|
|
|
|
|
|
}
|
|
|
|
|
|
return bytes;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* float 转 byte[]
|
|
|
|
|
|
* 小端
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param data
|
|
|
|
|
|
* @return
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static byte[] getFloatBytes(float data) {
|
|
|
|
|
|
int intBits = Float.floatToIntBits(data);
|
|
|
|
|
|
|
|
|
|
|
|
byte[] bytes = getIntBytes(intBits);
|
|
|
|
|
|
|
|
|
|
|
|
return bytes;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* byte[] 转 int
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param bytes
|
|
|
|
|
|
* @return
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static int getInt(byte[] bytes) {
|
|
|
|
|
|
int result = (int) ((fx & bytes[0])
|
|
|
|
|
|
| ((fx & bytes[1]) << 8)
|
|
|
|
|
|
| ((fx & bytes[2]) << 16)
|
|
|
|
|
|
| ((fx & bytes[3]) << 24));
|
|
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* byte[] 转 float
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param b
|
|
|
|
|
|
* @return
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static float getFloat(byte[] b) {
|
|
|
|
|
|
int l = getInt(b);
|
|
|
|
|
|
return Float.intBitsToFloat(l);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 将String转换为byte[]
|
2024-08-26 16:53:52 +08:00
|
|
|
|
* 可以与printHexBinary互转
|
2023-03-04 16:29:55 +08:00
|
|
|
|
* @param s String
|
|
|
|
|
|
* @return byte[]
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static byte[] hexStringToByteArray(String s) {
|
2024-08-26 16:53:52 +08:00
|
|
|
|
if (s == null || s.length() % 2 != 0) {
|
|
|
|
|
|
throw new IllegalArgumentException("Input string must not be null and its length must be even.");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
s = s.replaceAll("\\s", ""); // 使用正则表达式去除所有空白字符
|
|
|
|
|
|
|
2023-03-04 16:29:55 +08:00
|
|
|
|
int len = s.length();
|
|
|
|
|
|
byte[] data = new byte[len / 2];
|
2024-08-26 16:53:52 +08:00
|
|
|
|
|
2023-03-04 16:29:55 +08:00
|
|
|
|
for (int i = 0; i < len; i += 2) {
|
2024-08-26 16:53:52 +08:00
|
|
|
|
int byteValue = Character.digit(s.charAt(i), 16) << 4;
|
|
|
|
|
|
byteValue += Character.digit(s.charAt(i + 1), 16);
|
|
|
|
|
|
|
|
|
|
|
|
if (byteValue < 0) {
|
|
|
|
|
|
throw new IllegalArgumentException("Invalid character in the input string at index " + i);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
data[i / 2] = (byte) byteValue;
|
2023-03-04 16:29:55 +08:00
|
|
|
|
}
|
2024-08-26 16:53:52 +08:00
|
|
|
|
|
2023-03-04 16:29:55 +08:00
|
|
|
|
return data;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|