How can I identify ints that have a negative value that was converted from byte []?

I have a strange problem. Basically I use a queue server that accepts input only as byte [], so I take two int and int [] and converting them with ByteArrayOutputStream. It has worked fine so far, but since I am sending a lot of messages back and forth from the queue, I am trying to compress my int [] (it has several thousand elements, but most are zeros). I had the idea to take a sequence of zeros and turn them into negative values ​​(see the answer to this question .

But I am having problems because to convert the bytes [] back to the original format, I used the byte length [] and split it into 4 (since each int was 4 sizes and then scrolled it). Since I entered negative values ​​in the list, the size changed (by 1 to negative), which saves me from being able to unpack the data. I tried different ways to get the data in Byte [], and ByteArrayOutputStream seems to be the fastest I've tried so far, so if there isn’t anything faster, I prefer to stick with this method. Also in my related question, the accepted answer has a method that seems to fit perfectly into the existing loop structure, I already use hidden data (the decision to replace all zero with a negative number of a sequence of zeros).

Any ideas how I can distinguish between a stream of positive / negative bytes?

Here is the code:

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);
        }

    }

}
+3
source share
1 answer

The easiest way is probably to encode the size of the full list at the beginning, so instead of a list like {0, 1, 2, 3, -5}, you will have {0, 0, 0, 6, 0, 1, 2 , 3, -5} - then you just read the first 4 bytes as int, find that they are 6, allocate int [6] and unpack the rest of your stream into it.

0
source

All Articles