位移和将字符转换为Unicode转义字符串

3
我发现了一个Java类,可以将字节或字符转换为十六进制值。但我无法清楚地理解这段代码。你能解释一下这段代码是做什么的,或者告诉我在哪里可以找到更多相关资源吗?
public class UnicodeFormatter {

    static public String byteToHex(byte b) {
        // Returns hex String representation of byte b
        char hexDigit[] = {
            '0', '1', '2', '3', '4', '5', '6', '7',
            '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
        };
        char[] array = {hexDigit[(b >> 4) & 0x0f], hexDigit[b & 0x0f]};
        return new String(array);
    }

    static public String charToHex(char c) {
        // Returns hex String representation of char c
        byte hi = (byte) (c >>> 8);
        byte lo = (byte) (c & 0xff);
        return byteToHex(hi) + byteToHex(lo);
    }
} // class

1
我不确定其他部分,但是>>会将数字向右移动指定的位数。因此,b>>4相当于除以2^4(即16)。 - varatis
2个回答

4
首先,让我们从一些定义开始:
- 在Java中,一个字符(char)占用2个字节; - 每个字节由8个位(bits)组成; - 每个十六进制数字表示4个二进制位或位(bits)。
因此,一个字节可以由2个十六进制数字表示,即两组4位。 这正是byteToHex方法中所做的:它首先将字节分成两组4位,并使用hexDigit数组将每个字节映射到一个十六进制符号中。由于每组4位的十进制值永远不会大于或等于16(2^4),因此每组都将在hexDigits数组中具有映射。
例如,假设您想将数字29转换为十六进制:
1. 29在二进制中表示为00011101; 2. 将00011101分为两组4位,得到0001和1101; 3. 在程序中,第一组0001可以通过从29的二进制表示中移除最不重要的4位(1101)来获得。然后,0001将变为前4位。这可以在Java中通过(b >> 4)实现; 4. 第二组可通过b & 0x0f获得,这相当于00011101 & 00001111 = 00001101 = 1101。通过对该二进制数与0x0f进行按位与运算,您正在清除(设置为0)除了最不重要的4位之外的所有内容; 5. 最后,将每组转换为十进制数,得到1(0001)和13(1101),然后在十六进制系统中将它们分别映射为1和D。 6. 因此,数字29用十六进制表示为1D。
可以应用类似的逻辑于charToHex方法。唯一的区别是你正在转换2个字节,因为字符(char)占用2个字节。

2

这里的基本操作是将23转换为字符串,方法是将其变成2*10+3,然后将2和3转换为字符。

具体来说,我们首先要除以16,因为我们正在使用十六进制。

b >> 4意味着将位移4个空间,所以

12345678 >> 4 = 00001234  

然后在hexDigit数组中查找1234位置的值。

接着进行模运算,也称为取余数。在十进制示例中,这是通过截去左侧所有内容来找到3的结果。对于二进制,这里使用AND运算。

0x0f在位上是00001111,因此与一个字节进行AND运算时,它将把左侧4个空间改为0,只留下右侧4个空间。

12345678 & 0x0f = 00005678

再次,我们查找hexDigit数组中位置5678的值。请注意,我使用1-8作为位置标记,实际数据将全部为0和1。

编辑:第二个函数基本上执行相同的操作,它使用相同的 >>> 和 & 函数将 Unicode 字符拆分成字节。它似乎假设 Unicode 字符是16位的,所以将其向左移动8个位置以获取左侧8位,并使用 & 0xff 获取右侧8位。


我认为“byte”只是0和1,你怎么能移动12345678? - hungneox
请注意,我使用1-8作为位置标记。实际数据全部为0和1。 - Thomas
你知道它为什么有两部分吗?我猜它们是高位和低位?@Thomas - hungneox
1
Unicode字符由多个部分组成,因为2^8个字符对于某些语言来说不足够,所以根据编码方式,它可能有16位或32位。由于一个字节有8位,需要将其拆分才能使byteToHex在其上工作。 - Thomas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接