前言
最近在做一個遠端螢幕共享軟體,功能非常單一,隻能通過Android端檢視電腦的實時螢幕,一開始做法是電腦端不停捕獲目前螢幕截圖,壓縮後上傳到伺服器,Android不停的重新整理,但是結果有點不盡人意,效果太差了。其中并沒有将捕獲的螢幕儲存成jpg,然後發送,而是直接将BufferedImage轉換成 byte[]發送,當然伺服器也沒有存成檔案,也是使用byte[]存最新的螢幕資料,Android通過給定接口将byte[]轉換成圖像。
這裡面有個将InputStream中的資料轉換成BufferedImage的邏輯,我們可以使用 ImageIO這個類。

但是經過測試,JPEGCodec這個類似乎更好一些,但不知是不是如此,我不太确定。(ImageIO出現過錯誤,反而JPEGCodec卻沒有),但是注意的是,JPEGCodec并不屬于Java APIs的一部。
另外記憶體也占的太多,這歸根到底,是自己不會高深算法,哎。
于是也企圖研究一下,後來通過Socket來完成,這回延時也比較低,但是是屬于直連的形式,也就是手機通過Socket直接怼到電腦,電腦端不停的發送螢幕資料,可能在同一個區域網路,速度也比較快。另外經過優化,記憶體、CPU使用率都不是很高,視窗在拖動時Android端也差不多能流暢的顯示。
但是要做的并不是如此,不想隻限制在區域網路中,是以,我需要一個資料中轉伺服器。
電腦和Android通過Socket連接配接到伺服器,伺服器收到電腦發送的資料後傳遞給所有Android端。恩,大緻是這樣。
但是也遇到很多問題,如我要自定義一個格式,要将int轉byte[],byte[]在轉int,我想有必要記錄下轉換過程。
int轉byte
在java中,int為8位元組,二進制為32位,範圍在2147483648——2147483647之間,而byte在-128——127之間,那int轉byte就有些小計算了,大桶不可能完全放進小桶内,那麼這樣轉換逼不得已要把大桶敲碎,把一小塊放進小桶内,這會導緻什麼?當然是轉換後的值不一定是原來的值了。
下面這個輸出的byteValue也等于intValue,這是因為還沒有越界,byte還能容納。
好,再看下一個,這回輸出為-69,想知道内部是怎麼轉換的嗎?
在上面我們說過,要把大桶敲碎,在裝進去,在這裡,我要就要把int敲碎,要敲那部分呢?當然是敲他二進制的後8位。(此時我們要明白Java是采用補碼存儲整數)。
首先把187轉換為二進制。
然後敲出他的後8位,(補碼表示的時候第一位是符号位,0為正數,1為負數,剩餘是他的數值部分),是以他是一個負數,這也是為什麼輸出負數的原因。
然後将他的數值部分取反後+1(符号位不變)。
然後直接算100 0101的十進制為69,又因為最高位是1,是以他是負數,為-69,這裡要注意的是,不能算符号位,如果最終也算符号位的話,那麼基本資料類型的範圍将不是現在這樣。
int轉byte[]
我們知道了int轉byte的方法,那麼轉byte[]其實就是把4個8位分别放入到4個位元組中。
舉個例子,1154的二進制為以下。
而現在有四個byte,也就是byte[4]。
第一個byte為00000000,最終值為0 。
第二個byte為00000000,最終值為0 。
第三個byte為00000100,最終值為4。
第四個byte為10000010,最終值為-126(最高位為1,為負數,數值部分取反+1)。
那麼我們來測試一下,是不是這樣。
輸出結果。
byte[]轉int
在舉個例子,現在byte[4]中的值分别是以下值。
+21的補碼00010101。
-12的補碼11110100。
-89的補碼10100111。
最終二進制為00000000 00010101(+21) 11110100(-12) 10100111(-89),為1438887。
再來驗證一下。
輸出
在舉個負數例子.
-78的補碼為10110010。
+46的補碼為00101110。
最終10110010000000000000000000101110,由于最高位是1,是個負數,則将後面的數值取反+1為11001101111111111111111111010010,轉換成十進制就是-1308622802。驗證。
輸出
如有錯誤,請多多指出