【问题标题】:Bit shifting and bit mask - sample code位移位和位掩码 - 示例代码
【发布时间】:2015-05-19 14:03:38
【问题描述】:

我遇到了一些具有位掩码 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

在我看来,&amp;bytes[0] &amp; 0xff(bytes[1] &lt;&lt; 8) &amp; 0xff00) 两种情况下都没有对原始字节做任何事情。我错过了什么?

【问题讨论】:

    标签: java bit-manipulation


    【解决方案1】:
    int gzipHeader = ((int) bytes[0] & 0xff) | ((bytes[1] << 8) & 0xff00);
    

    byte 的类型是 Java 已签名。如果您将byte 转换为int,则为sign will be extended&amp; 0xff 用于屏蔽从符号扩展中获得的 1 位,有效地将 byte 视为无符号。

    0xff00 也一样,只是字节先左移 8 位。

    所以,它的作用是:

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

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

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

        【解决方案3】:

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

        【讨论】:

          【解决方案4】:

          byte 是有符号类型。如果您将 0xff 作为 byte 转换为 int,您将得到 -1。如果你真的想得到 255,转换后掩码。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-11-29
            • 2013-01-27
            • 1970-01-01
            • 2016-02-20
            • 2019-11-19
            • 1970-01-01
            相关资源
            最近更新 更多