淺談 &0xFF操作
在java.io.FilterOutputStream.DataOutputStream:與機器無關地寫入各種型別的資料以及String物件的二進位制形式,從高位開始寫。這樣一來,任何機器上任何DataInputStream都能夠讀取它們。所有方法都以“write”開頭,例如writeByte(),writeFloat()等。
java.io.FilterOutputStream.PrintStream最初的目的是為了以視覺化格式列印所有的基本資料型別以及String物件。這和DataOutputStream不同,它目的是將資料元素置入“流”中,使DataInputStream能夠可移植地重構它們。
對於如何把一串字串寫成二進位制,我一直迷惑不解,直到我看到下面的資訊:
字串的本質是char的序列,也就是char [ ]。因此,遍歷寫入每一個char,就完成了寫一個字串的功能!
那麼問題又來了,如何把char寫成二進位制呢?
英語字母有ASCII碼,可以把每個字元轉換成對應的數字,那麼漢字呢,日語呢,韓語呢,泰國語呢????????????????????????????????????????????????????
把心放肚子裡吧,這個問題前人早就已經解決了。世界上的絕大部分字元都有一張類似於ASCII碼錶的字元和編碼間的對映,那就是Unicode碼錶。看:
Unicode 字元編碼標準是固定長度的字元編碼方案,它包含了世界上幾乎所有現用語言的字元。有關 Unicode 的資訊可在最新版本的 The Unicode Standard 一書中找到,並可從 Unicode 協會 Web 站點(www.unicode.org)中找到。 Unicode 根據要編碼的資料型別使用兩種編碼格式:8
位和 16 位。預設編碼格式是 16 位,即每個字元是 16 位(兩個位元組)寬,並且通常顯示為 U+hhhh,其中 hhhh 是字元的十六進位制程式碼點。雖然生成的 65000 多個程式碼元素足以用於 編碼世界上主要語言的大多數字符,但 Unicode 標準還提供了一種擴充套件機制,允許編碼一百多萬個字元。擴充套件機制使用一對高位和低位代用字元來對擴充套件字元或補充字元進行編碼。第一個(或高位)代用字元具有 U+D800 和 U+DBFF 之間的程式碼值,而第二個(或低位)代用字元具有 U+DC00 和 U+DFFF 之間的程式碼值。
unicode碼真的可以用2個位元組表示世界上的絕大部分字元。
至此,當看到一個char時,我彷彿看到了它背後隱隱欲現的0-65535間的數字,當看到一個String時,我彷彿看到了一串數字!
所以,DataOutputStream.writeChars(str)的原始碼也就明晰了
public final void writeChars(String s) throws IOException {
int len = s.length();
for (int i = 0 ; i < len ; i++) {
int v = s.charAt(i);
out.write((v >>> 8) & 0xFF);
out.write((v >>> 0) & 0xFF);
}
incCount(len * 2);
}
所以除了要遍歷一遍string之外,其他的操作Yu DataOutputStream.writeShort(v)的原始碼沒什麼區別
public final void writeShort(int v) throws IOException {
out.write((v >>> 8) & 0xFF);
out.write((v >>> 0) & 0xFF);
incCount(2);
}
至此,就把一串字串寫成二進位制了。
但是,你有沒有一個疑問????????為什麼(v >>> 8) & 0xFF ??為什麼(v >>> 0) & 0xFF????不知道你有沒有,反正我有。
具體疑問:1 為什麼要用無符號的右移? 2 &0xFF不會使數的大小改變,為什麼還要 &0xFF?
先科普一下:
0(零)xFF是16進位制的255,也就是二進位制的 1111,1111
& AND 按位與操作,同時為1時才是1,否則為0.
————位移運算計算機中存的都是數的補碼,所以位移運算都是對補碼而言的————
<< 左移 右補0
>> 有符號右移 左補符號位,即:如果符號位是1 就左補1,如果符號位是0 就左補0
>>>無符號右移 ,顧名思義,統一左補0
————————————————————————————————————————
要想知道為什麼?我們應該想想,我們的目的是幹什麼的?開始已經講了:先取高8位寫入,再寫入低8位.。
0000,0000,0000,00113的二進位制原碼,假設要寫入的short字元對應的unicode碼是3。
0000,0000,0000,0000 這是">>>8"的結果
1111,1111
然後再 &0XFF
0000,0000 最終結果
這就得到了 3的原碼0000,0000,0000,0011 的高8位。
0000,0000,0000,0011 >>>0還是原始碼本身不變
1111,1111
&0XFF
0000,0011
最終結果
這就得到了 3的原碼0000,0000,0000,0011
的低8位。
其實,用有符號的右移>>也一樣得到高/低8位,因為右移操作不改變數本身,返回一個新值,就像String。所以 "&0xFF" 就像計算機中的一把剪刀,當‘&’操作符兩邊數的bit位數相同時不改變數的大小,只是專門截出一個位元組的長度。同理,&0x0F呢?得到4bits