带有扩展ascii代码的java字符串到字节数组(每个代码分配一个字节)

时间:2014-09-24 23:32:46

标签: java c++ c sockets

我有一个需要与C套接字客户端通信的java nio套接字服务器。 C套接字客户端使用大于127的ASCII代码向服务器发送数据,每个ASCII代码使用一个字节。服务器需要发回相同的内容。

我需要将字符串转换为具有相同长度的字节数组(每个代码一个字节)。 该字符串类似于1200üö001001001,其中包含127以上的一些ascii代码。 在我做的研究中,我没有找到解决方案。我试过这个

byte[] b = "1200üö001001001".getBytes("UTF-8");
byte[] b = "1200üö001001001".getBytes("US-ASCII");
byte[] b = "1200üö001001001".getBytes("ISO-8859-1");
byte[] b = "1200üö001001001".getBytes();

其中一些将üö转换为??或每个ASCII代码多个字节,导致字节数组和字符串之间的长度不同。

我需要一些帮助。

这是来自C套接字客户端的数据示例。点是客户的ascii代码。

<code>
0000 00 ff 31 32 30 30 fc f6 00 01 08 e1 e0 00 00 00 ..1200..........
0010 00 00 14 00 00 00 31 36 34 36 30 30 32 38 30 30 ......1646002800
0020 30 30 30 30 30 34 31 38 30 31 32 30 30 30 30 30 0000041801200000
0030 30 30 30 30 30 30 31 30 30 30 30 30 30 30 30 30 0000001000000000
0040 30 30 31 30 30 30 30 30 30 30 30 30 30 30 31 30 0010000000000010
0050 30 30 36 31 30 30 30 30 30 30 36 31 30 30 30 30 0061000000610000
0060 30 30 35 31 35 39 31 31 31 34 30 39 32 33 31 33 0051591114092313
0070 32 31 31 32 33 32 30 35 31 34 30 39 32 33 30 36 2112320514092306
0080 39 39 39 39 39 39 30 30 30 30 30 35 35 31 35 39 9999990000055159
0090 31 31 33 32 39 38 20 20 20 20 33 38 38 33 33 38 113298    388338
00a0 38 33 20 20 20 20 20 20 20 42 41 43 20 50 41 4e 83       XXX PAN
00b0 41 4d 41 20 54 45 53 54 3e 48 4f 57 41 52 44 20 AMA TEST>HOWARD
00c0 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 50                P
00d0 41 30 32 33 30 30 31 30 30 31 31 30 30 32 30 30 A023001001100200
00e0 33 37 30 30 30 32 35 30 30 31 31 38 34 30 38 34 3700025001184084
00f0 30 38 34 30 30 30 30 39 31 31 30 30 30 30 30 30 0840000911000000
0100 31

This is the code i use to convert from hex string to byte array

line 4 i convert from binary eg. 1101 to equvalent hex string eg `3F`
line 13 i take the bitmap in hex string eg. `"fcf6000108e1e0000000000014000000"`
        that contains 32 chars and try to convert to 16 bytes, but this results in 20 bytes
        because some chars takes more than one byte


       1     // Set bitmaps
       2     if ( String.copyValueOf(zeros).indexOf("1", 64) == -1 ) { zeros[0] = '0'; }
       3     tmp = String.copyValueOf(zeros);
       4     bits = binToHex(tmp);
       5
       6     // check bits to send
       7     if ( zeros[0] == '0') {
       8             bits = bits.substring(0, 16);
       9     }
      10
      11      // join message
      12      tmp = sb.toString();
      13      trm = isoCode + hexToASCII(bits) + tmp.substring(39);
      14      System.out.println("Trama respuesta " + (new Timestamp((new Date()).getTime())).toString() + " " + trm);

// here the code to send back the message from nio socet to client
   line mark with 100 add 2 space because there is a header with a short value that have the length of
   the message to be readed by socket client

            byte[] bytes = message.getBytes("ISO-8859-1");
            writeLength = message.length();
            //writeLength = bytes.length;
       100  writeBuffer = ByteBuffer.allocate(writeLength + 2);
            writeBuffer.putShort( (short)writeLength );
            writeBuffer.put(message.getBytes());   // Para test
            //this.writeBuffer.putChar('\n');
            writeBuffer.flip();

// auxiliar methods

    public  String hexToASCII(String hex){

              if(hex.length()%2 != 0){

                 System.err.println("requires EVEN number of chars");
                 return null;
              }
              StringBuilder sb = new StringBuilder();
              //Convert Hex 0232343536AB into two characters stream.
              for( int i=0; i < hex.length()-1; i+=2 ){
                   /*
                    * Grab the hex in pairs
                    */
                  String output = hex.substring(i, (i + 2));
                  /*
                   * Convert Hex to Decimal
                   */
                  int decimal = Integer.parseInt(output, 16);
                  sb.append((char)decimal);
              }
              return sb.toString();
        }

private final String HEXES = "0123456789ABCDEF";
private final String HEX[] = {"0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"};
private final String BIN[] = {"0000","0001","0010","0011","0100","0101","0110","0111","1000","1001","1010","1011","1100","1101","1110","1111"};

  /*
   *  Convert binary to hex string
   */
      public String binToHex(String bin) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < bin.length()-1 ; i += 4) {
            sb.append(HEX[ArrayUtils.indexOf(BIN, bin.substring(i, (i + 4)))]);
        } 
        return sb.toString();
    } 

This is the code i use to convert from hex string to byte array line 4 i convert from binary eg. 1101 to equvalent hex string eg `3F` line 13 i take the bitmap in hex string eg. `"fcf6000108e1e0000000000014000000"` that contains 32 chars and try to convert to 16 bytes, but this results in 20 bytes because some chars takes more than one byte 1 // Set bitmaps 2 if ( String.copyValueOf(zeros).indexOf("1", 64) == -1 ) { zeros[0] = '0'; } 3 tmp = String.copyValueOf(zeros); 4 bits = binToHex(tmp); 5 6 // check bits to send 7 if ( zeros[0] == '0') { 8 bits = bits.substring(0, 16); 9 } 10 11 // join message 12 tmp = sb.toString(); 13 trm = isoCode + hexToASCII(bits) + tmp.substring(39); 14 System.out.println("Trama respuesta " + (new Timestamp((new Date()).getTime())).toString() + " " + trm); // here the code to send back the message from nio socet to client line mark with 100 add 2 space because there is a header with a short value that have the length of the message to be readed by socket client byte[] bytes = message.getBytes("ISO-8859-1"); writeLength = message.length(); //writeLength = bytes.length; 100 writeBuffer = ByteBuffer.allocate(writeLength + 2); writeBuffer.putShort( (short)writeLength ); writeBuffer.put(message.getBytes()); // Para test //this.writeBuffer.putChar('\n'); writeBuffer.flip();

2 个答案:

答案 0 :(得分:0)

您正在混合字节和字符。有许多方法可以将像ü和ö这样的字符编码为字节,不同的编码每个字符占用不同的字节数。

请勿尝试将二进制流转换为字符串,除非您知道字节代表文本信息,并且您知道首先使用哪种编码将文本转换为字节。如果数据不是文本字符串,请不要尝试将其解释为文本字符串,只希望每个字节映射到合理的位置。

您可以直接使用字节数组或使用例如java.nio.ByteBuffer。如果数据中有文本字符串,则可以单独将特定字节转换为字符串。

答案 1 :(得分:0)

您的二进制位图因字符编码转换而受到严重影响。这样做是没有意义的。您只需将十六进制转换为byte []即可。

此代码建议方式:

String bitmapHex = "00112233445566778899aabbccddeeff"; 
String isoCode = "1200";
String data = "313030303030303031 and more";

byte[] bitmap = javax.xml.bind.DatatypeConverter.parseHexBinary(bitmapHex);

int datagramLength = 2 + isoCode.length() + bitmap.length + data.length();

ByteBuffer buffer = ByteBuffer.allocate(datagramLength);
buffer.order(ByteOrder.BIG_ENDIAN).putShort((short)datagramLength);
buffer.put(isoCode.getBytes(encodingName));
buffer.put(bitmap);
buffer.put(data.getBytes(encodingName));

byte[] output = buffer.array();