2012-04-29 122 views
3

我有一個奇怪的問題。基本上我使用的隊列服務器僅以byte []形式輸入,因此我使用兩個int和int []並使用ByteArrayOutputStream轉換它們。它迄今爲止工作得很好,但因爲我從隊列中傳遞了很多消息,所以我試圖壓縮我的int [](它有幾千個項目,但大多數都是零)。我有想到採取零序列並將它們變成負值(請參閱question的回答。如何識別具有從byte []轉換的負值的int?

但是,我遇到了問題,因爲要將我的字節[]恢復爲原來的格式byte []的長度並將它除以4(因爲每個int的大小是4,然後遍歷它)。由於我已將負值引入列表中,大小已更改(每個負1),這是我已經嘗試了不同的方式來獲取數據到Byte [],而ByteArrayOutputStream似乎是迄今爲止我嘗試過的最快的方式,除非有更快的速度,否則我更願意堅持使用這種方法。在我的鏈接問題中,接受的答案有一個方法,似乎完全適合現有的循環結構,我已經在使用隱式數據(取代所有ze ro的零序列的負數)。

任何想法如何區分正負字節流?

下面的代碼:

import java.io.ByteArrayInputStream; 
import java.io.ByteArrayOutputStream; 
import java.io.DataInputStream; 
import java.io.DataOutputStream; 
import java.io.IOException; 


public class compressionTest { 

    public static void main(String[] args) throws IOException { 
     //to convert to string 
     ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
     DataOutputStream dos = new DataOutputStream(baos); 
     //data 
     int data1 = 10; 
     int data2 = 43; 
     int[] sub = { 10, 40, 0, 0, 0, 30, 0, 100, 0, 0, 0, 0 }; //should become [10, 40, -3, 30, -1, 100, -4] 
     //add data to bytes 
     dos.writeInt(data1); 
     dos.writeInt(data2); 
     int count_zero = 0; 
     for (int j : sub) { 
      if (j == 0) { 
       //System.out.println("Equals 0!"); 
       count_zero = count_zero + 1; 
      } else { 
       if (count_zero != 0) { 
        dos.write(-1 * count_zero); 
        //System.out.println(-1 * count_zero); 
        count_zero = 0; 

       } 
       dos.writeInt(j); //orginally I just had this under the for loop and it works(if you delete the if data above) 
      } 
     } 
     byte[] bytes = baos.toByteArray(); 

     System.out.println(bytes); //this is the data I send 

     //now bring it back 
     ByteArrayInputStream bais = new ByteArrayInputStream(bytes); 
     DataInputStream dis = new DataInputStream(bais); 
     System.out.println("****"); 
     int data1_return = 0; 
     int data2_return = 0; 
     System.out.println("size of byte[] is " + bytes.length); 
     //ArrayList<Integer> sub_return = new ArrayList<Integer>(); 
     int[] sub_return = new int[(bytes.length/4)-2]; //size of data minus first two intgers 
     for (int item = 0; item<(bytes.length/4);item++){ 
      if (item == 0) { 
       data1_return = dis.readInt(); 
      } else if (item == 1) { 
       data2_return = dis.readInt(); 
      } else { 
       sub_return[item-2] = dis.readInt(); 
      } 
     } 

     //print out the data 
     System.out.println(data1_return); 
     System.out.println(data2_return); 
     for (int i : sub_return) { 
      System.out.println(i); 
     } 

    } 

} 
+0

它們不是正數和負數字節,它們是整數。因此,您應該將四個字節組合成一個整數。然後可以檢查整數是否爲負值或正值。此外,如果整數是負數,則四個整數中的第一個將在Little Endian中爲負,在Big Endian中爲最後一個。一個重要的評論是你的算法不會工作,因爲尾部零不會被髮送到接收器! –

回答

0

最簡單的方法可能是完整的列表的大小在開始的,因此而不是一個列表,就像編碼{0,1,2,3, - 5}你會有{0,0,0,6,0,1,2,3,-5} - 那麼你只是讀取前4個字節爲int,找到它們等於6,分配一個int [6],並將其餘的流解壓到它。

+0

爲什麼「分配一個int [6]」而不是'new int [5]'?我問,因爲大小似乎是錯誤的,'int [6]'不是在C中的方式在Java中的類型。 –

+0

除非我誤解了原來的問題,否則我提供的列表將重複解碼爲0x00010203 6次一次對於字節序列0,1,2,3,然後對-5重複5次)。然後'分配int [6]'我的意思是使用'new int [6]'創建數組來存儲結果。 – Jules