How to correctly use BufferedInputStream?

4

I'm creating an application in which I need to read from a video file and transmit packets of data that can be read back into memory. I am using the Ogg video format because it is open source and because I found it simpler to understand. I used BufferedInputStream to read from the file, but as the first 28 bytes are header information I opted to use the buffer.read(byte[]) method as follows:

byte[] buffer = new byte[28];
FileInputStream in = new FileInputStream("/path/video.ogv");
BufferedInputStream buffStream = new BufferedInputStream(in);
buffStream(buffer);

So, I can read a sequence of bytes faster. When I inspect the buffer element in the eclipse debug, I noticed that values above 128 are negative, this I think is due to the fact that the maximum number that I can represent with 1 byte is 128. I know that the values are corrupted because when I open the file in the link , I can see the correct value in hexadecimal. For example, the value that corresponds to B5 = 181(dec) is set to -75. How can I use this method and work around this data corruption?

Note: Using a video decoder that already does this transparently is not an option. It is necessary to be this way because I am developing a distributed application and the data packages will be destined for other computers.

    
asked by anonymous 01.08.2017 / 23:36

1 answer

4

That's not corruption of data. It's an annoying catch of the Java language.

Most programming languages represent a byte as a number from 0 to 255, that is, an unsigned value. For some reason, Java wanted to be different and decided that the byte has a signed signal, so it has values from -128 to 127.

In the binary form, the relative values of the bits in the unsigned schema are 128 (most significant), 64, 32, 16, 8, 4, 2, and 1 (least significant). In Java, the first value is -128 instead of 128.

In this way, to convert a value in the range -128 to 127 for the range 0 to 255, you do this:

public static int tirarSinalDoByte(byte a) {
    return (a + 256) % 256;
}

Or this other implementation (more efficient, but a little less didactic):

public static int tirarSinalDoByte(byte a) {
    return a & 0xFF;
}

To convert back:

public static byte formarByte(int a) {
    if (tirarSinalDoByte(a) != a) throw new IllegalArgumentException();
    return (byte) a;
}

In this back conversion, if you are sure that the a value is always in the correct range or you want to neglect anything other than the last 8 bits if it is not, you can either remove this if or else only cast% to byte without having to call a specific function to do this.

    
01.08.2017 / 23:48