2015-05-19 37 views
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的幻數被寫入是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)。我錯過了什麼?

回答

5
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位左,屏蔽掉符號擴展位
  • |
結合的值

請注意,左移有效地交換了字節。

0

顯然,目的是讀取bytes的第一個單詞,並通過適當的遮罩和移位將它們存儲在gzipHeader中。更準確地說,第一部分屏蔽了第一個字節,而第二部分屏蔽了已經移位了8位的第二個字節。 |將兩個位掩碼結合到一個int

將結果值與定義的值GZIPInputStream.GZIP_MAGIC進行比較,以確定前兩個字節是否是用gzip壓縮的數據的定義開始。

0

byte是一種簽名類型。如果您將0xff轉換爲byteint,則會得到-1。如果您確實想獲得255,則在轉換後進行掩碼。