位移和位掩码 - 样例代码

4

我遇到了一些代码,其中有位掩码0xff0xff00,或以16位二进制形式表示为00000000 1111111111111111 00000000

/**
 * Function to check if the given string is in GZIP Format.
 *
 * @param inString String to check.
 * @return True if GZIP Compressed otherwise false.
 */
public static boolean isStringCompressed(String inString)
{
    try
    {
        byte[] bytes = inString.getBytes("ISO-8859-1");
        int gzipHeader = ((int) bytes[0] & 0xff)
            | ((bytes[1] << 8) & 0xff00);
        return GZIPInputStream.GZIP_MAGIC == gzipHeader;
    } catch (Exception e)
    {
        return false;
    }
}

我试图弄清楚在这种情况下(针对字节数组),使用这些位掩码的目的是什么。我看不出会有什么区别?

在GZip压缩字符串的上下文中,因为这个方法似乎是为GZip魔术数字编写的,所以该魔术数字是35615,十六进制为8B1F,二进制为10001011 00011111

我是否正确地认为这会交换字节顺序?例如,假设我的输入字符串为\u001f\u008b

bytes[0] & 0xff00
 bytes[0] = 1f = 00011111
          & ff = 11111111
                 --------
               = 00011111

bytes[1] << 8
 bytes[1] = 8b = 10001011
          << 8 = 10001011 00000000

((bytes[1] << 8) & 0xff00)
= 10001011 00000000 & 0xff00
= 10001011 00000000 
  11111111 00000000 &
-------------------
  10001011 00000000

所以
00000000 00011111
10001011 00000000 |
-----------------
10001011 00011111 = 8B1F

对我来说,无论是在bytes[0] & 0xff还是(bytes[1] << 8) & 0xff00)的情况下,&似乎对原始字节没有任何影响。我错过了什么吗?
4个回答

7
int gzipHeader = ((int) bytes[0] & 0xff) | ((bytes[1] << 8) & 0xff00);

在Java中,类型byte有符号的。如果将byte强制转换为int,它的符号将被扩展& 0xff用于屏蔽从符号扩展中获得的1位,有效地将byte视为无符号。
对于0xff00也是一样的,只不过首先将字节左移8位。
所以,这样做的目的是:
  • 取第一个字节bytes [0],将其转换为int并屏蔽符号扩展的位(将字节视为无符号)
  • 取第二个字节,将其转换为int,向左移动8位,并屏蔽符号扩展的位
  • 使用|组合值
请注意,左移操作实际上交换了字节顺序。

1
显然,目的是读取bytes的第一个单词并通过适当的掩码和移位将其存储在gzipHeader中。 更精确地说,第一部分精确地屏蔽了第一个字节,而第二部分则屏蔽了第二个字节,已经向左移动了8个位。 |将两个位掩码组合成一个int
生成的值与定义的值GZIPInputStream.GZIP_MAGIC进行比较,以确定前两个字节是否为使用gzip压缩的数据的定义开头。

1
这是一个克服大端/小端问题的技巧。它强制将前两个字节解释为小端,即[0]包含低位字节,[1]包含高位字节。

0

byte 是一种有符号类型。如果你将 0xff 转换为 byte,再转换为 int,你会得到 -1。如果你真的想要得到 255,那么在转换后进行掩码操作。


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