1

I am trying to write a binary string into a file and afterwords read it and present it in a hex representation. This is my code:

import java.io.*;
import java.math.BigInteger;

public class TestByte {
      public static void main(String[] argv) throws IOException {

String bin = "101101010110001000010011000000000100010000000001000000000000000100000000000000000000000000000000000010110000000000111111000101010001100000000000000000000000000000001000000000000000000000111110011111000000000010110011";

    //write binary file
    DataOutputStream out = null;
    File fileout = new File("binout.bin");
    out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(fileout)));
    int indx = 0;
    for (int i = 0; i < bin.length()/8; i++){
        System.out.println(bin.substring(indx, indx+8));
        byte[] bytesout = new BigInteger(bin.substring(indx, indx+8),2).toByteArray();
        out.write(bytesout);
        indx += 8;
    }
    out.close();

    //read binary file
    File filein = new File("binout.bin");       
    byte[] bytesin = new byte[(int) filein.length()];
    FileInputStream inputStream = new FileInputStream(filein);
    inputStream.read(bytesin);
    inputStream.close();

    StringBuilder sb = new StringBuilder();
    for (byte b : bytesin) {
        sb.append(String.format("%02X ", b));
    }
    System.out.println(sb.toString());      
}}

The program works, however, there are some inconsistencies with the data. This is the output:

10110101 01100010 00010011 00000000 01000100 00000001 00000000 00000001 00000000 00000000 00000000 00000000 00001011 00000000 00111111 00010101 00011000 00000000 00000000 00000000 00001000 00000000 00000000 00111110 01111100 00000000 10110011

00 B5 62 13 00 44 01 00 01 00 00 00 00 0B 00 3F 15 18 00 00 00 08 00 00 3E 7C 00 00 B3

As you can see, I have broken the binary string into pieces of 8 bits so it would be easier to follow the numbers. The inconsistency is the Hex representation. It seems there is an extra "00" at the beginning of the hex string, which should not be there. Also there is an extra "00" in the end of the string, the should be only one "00" before the "B3".

Can anyone shed some light on this problem and/or make the solution more elegant? Any help would be appreciated. Thank you.

  • Which version of Java is that? – fge Mar 09 '16 at 10:20
  • thats is the JDK version jdk1.8.0_66 the java version is 8 update 73 –  Mar 09 '16 at 10:22
  • OK, well, for starters, you should (learn to) use try with resources for handling your resources :) – fge Mar 09 '16 at 10:31
  • 1
    The problem is `BigInteger` is signed ([two's complement](https://en.wikipedia.org/wiki/Two%27s_complement)) and needs a `0` bit to indicate a positivie number, when you convert 8 bits (unsigned) you'll get a 9 bit signed integer. Solution: Don't use a hack like BigInteger, implement the bit shifting yourself. – BeyelerStudios Mar 09 '16 at 10:32
  • @BeyelerStudios that was my thought too... However I have just tested: `new BigInteger("10000100", 2).toByteArray().length` is 2 – fge Mar 09 '16 at 10:33
  • @fge that would support the 9 bit theory since 9 bit require 2 bytes ;) also note that BigInteger is signed, but the implementation specifics may be undefined, i.e. could get different results on different VMs... – BeyelerStudios Mar 09 '16 at 10:34
  • @BeyelerStudios how do i solve this problem? in the main program when i convert some of the values to binary i do calculate their 2's complement, but that has nothing to do with this problem. how can i resolve it? –  Mar 09 '16 at 10:35
  • @BeyelerStudios sorry, my mistake; the problem however is that `new BigInteger("00011000").toByteArray().length` is _also_ 2. – fge Mar 09 '16 at 10:36
  • @BeyelerStudios what do you mean by "implement the bit shift yourself"? –  Mar 09 '16 at 10:39
  • @fge the [docs](https://docs.oracle.com/javase/7/docs/api/java/math/BigInteger.html#toByteArray()) only specify that it will indeed return a two's complement and that the byte array returned is compatible with the byte array constructor. There are no promises made on the length of said array, so that's what I mean with implementation dependent: the length is unspecified, but at least the two's complement has to fit in it. – BeyelerStudios Mar 09 '16 at 10:39
  • is it possible to write the binary string to a file without converting it to bytes? and therefore not using the BigInteger command? –  Mar 09 '16 at 10:41
  • 1
    @DanyLavrov it is possible using a simple int; you can `Integer.parseInt(someString, 2)` then write `(byte) (theInt & 0xff)`. And by the way you don't need a `DataOuputStream`: just use a plain `ÒutputStream` and `.write()` the individual bytes – fge Mar 09 '16 at 10:43
  • @fge thank you that worked. if i change the "DataOutputStream" to "OutputStraem" what would be the right declaration of "out"? –  Mar 09 '16 at 10:54
  • 1
    Possible duplicate of [Converting a String representation of bits to a byte](http://stackoverflow.com/questions/8275474/converting-a-string-representation-of-bits-to-a-byte) – BeyelerStudios Mar 09 '16 at 10:57

1 Answers1

0

You should use Integer.parseInt like this to avoid the sign / 2s complement problem.

This is working for me:

for (int i = 0; i < bin.length()/8; i++){
    System.out.println(bin.substring(indx, indx+8));
    int b = Integer.parseInt(bin.substring(indx, indx+8),2);
    out.writeByte(b);
    indx += 8;
}

See also this: Converting a String representation of bits to a byte

Community
  • 1
  • 1
riskop
  • 1,693
  • 1
  • 16
  • 34