Java 通过串行端口发送时,无法将字节数组转换为字符数组,反之亦然
我必须做以下事情Java 通过串行端口发送时,无法将字节数组转换为字符数组,反之亦然,java,binary,serial-port,bytearray,arrays,Java,Binary,Serial Port,Bytearray,Arrays,我必须做以下事情 在包含4个字节的字符数组的末尾附加2个十六进制字节,因此结果是6个字节 将上述6字节数组转换为字符数组,以将其传递给函数CRCRResult。(该函数仅接受字符数组) 最后将crc 2字节合并到6字节的末尾 我已经在单独的java类中测试了下面的程序,它成功了 public class CharBytetest { public static void main(String[] args) { char charbuffer1[] = {
public class CharBytetest
{
public static void main(String[] args)
{
char charbuffer1[] = {0x01,0x05,0x00,0x03};
byte[] bufferbyte1 = new String(charbuffer1).getBytes();// converts chararray to byte array
byte byte4 = (byte)0xFF;
byte byte5 = (byte)0x00;
byte[] bufferbytemerge1 = new byte[bufferbyte1.length+2];
System.arraycopy(bufferbyte1, 0, bufferbytemerge1, 0, bufferbyte1.length);
bufferbytemerge1[bufferbyte1.length]= byte4;
bufferbytemerge1[bufferbyte1.length +1 ]= byte5;
//bufferbytemerge1 contains 6 byte (charbuffer1 + byte4 + byte5 )
String str = new String(bufferbytemerge1);
//bufferbytemerge1 converted to char array
char[] charbuffer2 = str.toCharArray();
byte[] bufferbyte2 = new String(charbuffer2).getBytes();
int crcresult;
//char array sent to crc function
crcresult = CalculateCRC.CRC16(charbuffer2,6);
byte byte1 = (byte)((crcresult >> 8) & 0xFF); // first 8 bits of last 16 bits
byte byte0 = (byte)(crcresult & 0xFF); // last 8 bits
byte[] bufferbytemerge2 = new byte[bufferbyte2.length + 2];
System.arraycopy(bufferbyte2, 0, bufferbytemerge2, 0, bufferbyte2.length);// copy original data stored in bytebuffer
bufferbytemerge2[bufferbyte2.length] = byte1; // append crc16 byte 1
bufferbytemerge2[bufferbyte2.length + 1] = byte0; // append crc16 byte 2
//bufferbytemerge2 contains total 8 bytes
for (byte b : bufferbytemerge2){
System.out.format("0X%x ", b);
}
}
}
所看到的输出是
0X1 0X5 0X0 0X3 0Xff 0X0 0X7c 0X3a
但我的问题是,当我实现上面的东西时,在串行端口中发送“bufferbytemerge2”,特别是modbus,转换错误被视为
java.lang.ArraIndexOutOfBoundsException : 65454
at com.wexsnet.wesModbus.comm.req.CalculateCRC.crc16 <CalculateCRC.java:59>
java.lang.ArraIndexOutOfBoundsException:65454
在com.wexsnet.wesModbus.comm.req.calculaterc.crc16上
我试图分析每一步得到的字节,似乎问题出在第二步。当bufferbytemerge1转换为字符数组时
根据上面的代码,“bufferbyte2”应该包含01 05 00 03 FF 00,但当我尝试发送“bufferbyte2”时,它发送的是01 05 00 03 ef bf 00
这是因为将“bufferbytemerge1”字节数组转换为字符数组“charbuffer2”是不正确的。或将“charbuffer2”字符数组转换为字节数组“bufferbyte2”不正确。请帮助我们如何正确转换它。不要在Java中使用
char
来保存字节值。我意识到这是C语言中的标准实践,但在Java中,字节只属于byte
数组
每次将字节转换为字符串或将字符串转换为字节时,您都在使用字符集的编码器或解码器。在许多字符集(包括UTF-8,这是您的系统显然使用的),并不是每个字节值都可以转换为一个字符;这些字节将被丢弃或替换为一些默认数字。在许多字符集中,有些字符并不对应于单个字节,而是对应于多个字节,这就是ef-bf
的来源
这就是为什么使用新字符串(字节[])
和String.getByes()
会损坏数据
不要使用char
数组。不要将字节转换为字符串或从字符串转换为字节。仅使用byte
数组来保存字节
如果要将字节
数组转换为16位值的数组,请使用将其转换为短
数组:
short[] sixteenBitValues = new short[byteArray.length / 2];
ByteBuffer.wrap(byteArray).asShortBuffer().get(sixteenBitValues);
通常,如果要将字节附加到字节数组中,应使用字节缓冲符
:
ByteBuffer buffer = ByteBuffer.allocate(oldByteArray.length + 2);
buffer.put(oldByteArray);
buffer.asShortBuffer().put(crcresult);
byte[] newByteArray = buffer.array();
如果您的CRC16方法仅对char
数组进行操作,则需要避免使用String或任何其他将调用字符集编码的方法,并强制自己将字节设置为char
值:
char[] charBuffer2 = new char[byteBuffer.length];
for (int i = 0; i < byteBuffer.length; i++) {
charBuffer2[i] = (char) (byteBuffer[i] & 0xff);
}
char[]charBuffer2=新字符[byteBuffer.length];
for(int i=0;i
听起来您的CRC16方法是基于C的假设,即char
保存一个字节,因此如果您对该类有任何控制权,则应将其更改为接受byte[]
参数。不要在Java中使用char
保存字节值。我意识到这是C语言中的标准实践,但在Java中,字节只属于byte
数组
每次将字节转换为字符串或将字符串转换为字节时,您都在使用字符集的编码器或解码器。在许多字符集(包括UTF-8,这是您的系统显然使用的),并不是每个字节值都可以转换为一个字符;这些字节将被丢弃或替换为一些默认数字。在许多字符集中,有些字符并不对应于单个字节,而是对应于多个字节,这就是ef-bf
的来源
这就是为什么使用新字符串(字节[])
和String.getByes()
会损坏数据
不要使用char
数组。不要将字节转换为字符串或从字符串转换为字节。仅使用byte
数组来保存字节
如果要将字节
数组转换为16位值的数组,请使用将其转换为短
数组:
short[] sixteenBitValues = new short[byteArray.length / 2];
ByteBuffer.wrap(byteArray).asShortBuffer().get(sixteenBitValues);
通常,如果要将字节附加到字节数组中,应使用字节缓冲符
:
ByteBuffer buffer = ByteBuffer.allocate(oldByteArray.length + 2);
buffer.put(oldByteArray);
buffer.asShortBuffer().put(crcresult);
byte[] newByteArray = buffer.array();
如果您的CRC16方法仅对char
数组进行操作,则需要避免使用String或任何其他将调用字符集编码的方法,并强制自己将字节设置为char
值:
char[] charBuffer2 = new char[byteBuffer.length];
for (int i = 0; i < byteBuffer.length; i++) {
charBuffer2[i] = (char) (byteBuffer[i] & 0xff);
}
char[]charBuffer2=新字符[byteBuffer.length];
for(int i=0;i
听起来您的CRC16方法是基于C的假设,即char
包含一个字节,因此如果您对该类有任何控制权,则应将其更改为接受byte[]
参数。当您调用新字符串(byte[])
时,您正在使用无效编码调用未指定的行为。当您调用新字符串(字节[])
时,您正在使用无效编码调用未指定的行为。谢谢你的回复。但是我需要将字节数组转换为字符数组,因为函数crcresult接受字符数组。那么如何有效地转换它。另外,当我使用字节缓冲区时,错误被视为“导入java/nio/ByteBuffer无效。更新了我的答案。至于导入错误,您的导入行应该如下所示:import java.nio.ByteBuffer;
我得到以下错误:“语义错误:导入“java/nio/ByteBuffer”无效,因为它未命名包中的类型。" . 如何继续前进。请建议。我正在使用eclipseIf您可以控制该API,请修复它。如果您无法控制该API,则应立即使用API的字符集将返回的字节数组转换为字符串或字符缓冲区。就我个人而言,我会添加一条评论,说明API是有保证的(