我遇到了一些代码,这些代码具有位掩码0xff
和0xff00
或16位二进制形式00000000 11111111
和11111111 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)
似乎都没有对原始字节做任何事情。我错过了什么?
答案 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转换为byte
到int
,则得到-1。如果你真的想要获得255,那么在转换后进行掩码。