位移位和位掩码 - 示例代码
Bit shifting and bit mask - sample code
我遇到过一些具有位掩码 0xff
和 0xff00
或 16 位二进制形式 00000000 11111111
和 11111111 00000000
.[=24= 的代码]
/**
* 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)
两种情况下,&
似乎都没有对原始字节做任何事情。我错过了什么?
显然目的是读取 bytes
的第一个单词并通过适当的掩码和移位将它们存储在 gzipHeader
中。更准确地说,第一部分恰好屏蔽了第一个字节,而第二部分屏蔽了已经移动了 8 位的第二个字节。 |
将两个位掩码组合成 int
.
将结果值与定义值 GZIPInputStream.GZIP_MAGIC
进行比较,以确定前两个字节是否是使用 gzip 压缩的数据的定义开头。
byte
是有符号类型。如果将 0xff 作为 byte
转换为 int
,则会得到 -1。如果你真的想得到255,转换后屏蔽。
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位,并屏蔽掉符号扩展位
- 将这些值与
|
合并
请注意,左移有效地交换了字节。
这是克服big-endian/little-endian问题的技巧。它强制将前两个字节解释为小端字节序,即 [0]
包含 low
字节,[1]
包含 high
字节。
我遇到过一些具有位掩码 0xff
和 0xff00
或 16 位二进制形式 00000000 11111111
和 11111111 00000000
.[=24= 的代码]
/**
* 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)
两种情况下,&
似乎都没有对原始字节做任何事情。我错过了什么?
显然目的是读取 bytes
的第一个单词并通过适当的掩码和移位将它们存储在 gzipHeader
中。更准确地说,第一部分恰好屏蔽了第一个字节,而第二部分屏蔽了已经移动了 8 位的第二个字节。 |
将两个位掩码组合成 int
.
将结果值与定义值 GZIPInputStream.GZIP_MAGIC
进行比较,以确定前两个字节是否是使用 gzip 压缩的数据的定义开头。
byte
是有符号类型。如果将 0xff 作为 byte
转换为 int
,则会得到 -1。如果你真的想得到255,转换后屏蔽。
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位,并屏蔽掉符号扩展位 - 将这些值与
|
合并
请注意,左移有效地交换了字节。
这是克服big-endian/little-endian问题的技巧。它强制将前两个字节解释为小端字节序,即 [0]
包含 low
字节,[1]
包含 high
字节。