将char []转换为byte []而不会丢失'bits'

时间:2012-07-17 14:50:36

标签: java android types unsigned

我正在使用Java开发Android 2.3.3应用程序。

这个应用程序是一个iOS代码,无符号数据类型移植到Java。

在iOS上,它适用于UInt16UInt8。在一个案例中,改为使用byte[]我正在使用char[]

但我知道我必须使用DatagramPacketchar[]作为byte[]发送。

如果char []的一个元素是128,我该如何插入byte []并且接收器获得128.我不知道如果我这样做会发生什么:

char c = (char)128;
byte b = (byte)c;

哪个值为b? 128 = 10000000. b = -1或b = 127?

如何在不丢失任何的情况下将char[]转换为byte[]

2 个答案:

答案 0 :(得分:8)

在Java char中是无符号的16位数。因此,您可以直接将uint16转换为char,而无需执行任何其他操作。

对于无符号8位数量,您有2个选项:

  1. 使用byte。它还包含8位。你不会因为签名而丢失任何内容。但是,如果您使用它进行算术运算,则需要记住Java会自动将byte扩展为int并对其进行符号扩展。为了防止这种情况,总是像这样掩饰它:

    字节b; int foo = 5 *(b& 0xFF);

  2. 使用char。它是无符号的,可以保存16位,因此8位非常适合。要将byte放入char,请执行以下操作:

    字节b; char c =(char)(b& 0xFF); //屏蔽低8位

  3. char放入byte只需执行:

    char c;
    byte b = (byte)c; // Truncates to 8 bits
    

    请注意Java中的byte已签名,因此每当您使用它进行算术运算时,您只需要屏蔽低8位(以防止符号扩展)。像这样:

    byte b;
    int foo = (b & 0xFF);
    

    您可以使用字节执行所需的所有正常按位操作,而无需屏蔽:

    byte b;
    if (b & 0x80) ... // Test a flag
    b |= 0x40; // Set a flag
    b ^= 0x20; // Flip a flag from 0 to 1 or 1 to 0
    b ^= ~0x10; // Clear a flag
    byte x = b << 3; // Shift left 3 bits and assign
    byte x = b >>> 4; // Shift right 4 bits and assign (WITHOUT sign extension)
    

答案 1 :(得分:2)

我认为您需要重新考虑您的方法,因此您最终无需将char[]转换为byte[]

如果您的数据确实是字符,那么您希望查看各种序列化技术,例如使用new String(char[])创建字符串,然后使用getBytes(Charset)获取由给定{编码的字节{3}}(因为,当用ASCII或UTF-8或UTF-16等编码时,相同的字符会产生不同的字节。)

但是根据你的问题,听起来你并没有真正使用字符,你只是使用char作为16位类型。如果是这样,那么进行转换并不困难,具体如下:

byte[] toBytes(char[] chars) {
    byte[] bytes = new byte[chars.length * 2];
    int ci, bi;
    char ch;

    bi = 0;
    for (ci = 0; ci < chars.length; ++ci) {
        ch = chars[ci];
        bytes[bi++] = (byte)((ch & 0xFF00) >> 8);
        bytes[bi++] = (byte)(ch & 0x00FF);
    }

    return bytes;
}

如果您希望结果是小端,请反转掩码。

但是,我会再看一下你的整体方法并尽量避免这种情况。