位移和位掩码 - 示例代码

时间:2015-05-19 14:03:38

标签: java bit-manipulation

我遇到了一些代码,这些代码具有位掩码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编写的,幻数为356158B1F为十六进制,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 个答案:

答案 0 :(得分:6)

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

类型byte是Java 签名。如果您将byte投射到int,则其sign will be extended& 0xff用于屏蔽您从符号扩展中获得的1位,有效地将byte视为未签名。

同样适用于0xff00,除了该字节首先向左移位8位。

所以,这样做是:

  • 取第一个字节bytes[0],将其转换为int并屏蔽符号扩展位(将字节视为无符号)
  • 取第二个字节,将其转换为int,将其向左移8位,然后屏蔽符号扩展位
  • 将值与|
  • 合并

请注意,左移有效地交换了字节。

答案 1 :(得分:1)

这是克服big-endian/little-endian问题的一个技巧。它强制将前两个字节解释为little-endian,即[0]包含low字节,[1]包含high字节。

答案 2 :(得分:0)

显然,目的是阅读bytes的第一个单词,并通过适当的屏蔽和移位将它们存储在gzipHeader中。更确切地说,第一部分完全屏蔽了第一个字节,而第二部分屏蔽了第二个字节,已经移位了8位。 |将位掩码与int组合在一起。

将结果值与定义的值GZIPInputStream.GZIP_MAGIC进行比较,以确定前两个字节是否是使用gzip压缩的数据的已定义开头。

答案 3 :(得分:0)

byte是签名类型。如果将0xff转换为byteint,则得到-1。如果你真的想要获得255,那么在转换后进行掩码。