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[] = {

我必须做以下事情

  • 在包含4个字节的字符数组的末尾附加2个十六进制字节,因此结果是6个字节

  • 将上述6字节数组转换为字符数组,以将其传递给函数CRCRResult。(该函数仅接受字符数组)

  • 最后将crc 2字节合并到6字节的末尾

  • 我已经在单独的java类中测试了下面的程序,它成功了

      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是有保证的(