0

I have a big file with more than 100000 bytes that look like this "0xCA,0xFE,0xBA,0xBE,0x0,0x0,0x0,0x34,0x0,0xBB,0x1,0x0,0x35,0x6D,0x65,0x2F, 0x6D" I would like to retrieve the content of the file and store each byte in a byte array as a byte, my jar retrieves them as Strings but then impossible to transform them into functional byte how can I do?

    public static byte[] genClasses() throws IOException {
    InputStream stream = LonelyMod.class.getResourceAsStream("/o.txt");
    BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
    ArrayList<Byte> bytes = new ArrayList<>();
    String line;
    while((line = reader.readLine()) != null) {
        ArrayList<Byte> tempBytes = new ArrayList<>();
        for(String s : line.split(",")) {
            tempBytes.add(/* here im supposed to add the s String as a byte*/);
        }
        bytes.addAll(tempBytes);
    }
    byte[] bytes1 = new byte[bytes.size()];
    int i = 0;
    for(byte b : bytes) {
        bytes1[i] = b;
        i++;
    }
    return bytes1;
}

thanks for your help

Soros
  • 3
  • 1
  • *impossible to transform them into functional byte*: What specific problem are you having? What has your research suggested about [converting hex strings to bytes](https://stackoverflow.com/questions/140131/convert-a-string-representation-of-a-hex-dump-to-a-byte-array-using-java)? – chrylis -cautiouslyoptimistic- Aug 09 '21 at 22:50
  • First of all: **never** use a `Reader` to read a binary file and **never** store binary (non-text) data in a `String`, it's a bad idea and will do bad stuff. Use the `InputStream` directly to read `byte[]`. By the time you've got a `String`, you've already irreparably mangled the data. Also: `CAFEBABE` suggests that the input is actually a Java `.class` file, by the way. – Joachim Sauer Aug 09 '21 at 22:54
  • @chrylis-cautiouslyoptimistic- actually when i do use Byte.valueOf or Byte.parseByte i get the following error : Error: java.lang.NumberFormatException: For input string: "0xCA" , I looked for it but it didn't seem to be what I wanted exactly I'll try it anyway – Soros Aug 09 '21 at 22:57
  • Are those strings or simply unsigned hex representations of 8 bit values (bytes)? They appear to be bytes since each hex digit is 4 bits. – WJS Aug 09 '21 at 22:59
  • @JoachimSauer It's a jar, I got the content in byte and I wrote it in a text file, the goal is to load it in another application at runtime, I don't have access to the real jar that's why the bytes are written in a text file separated by a comma, let me know if there is a better way to do that, given the size of the file I can't just create an byte array in the code because I'm over the limit – Soros Aug 09 '21 at 23:01
  • @WJS thoose are bytes , at the very beginning I stored it in my code(with a byte arrayà but there are too many of them so I had to put them in a text so that the jar could be built – Soros Aug 09 '21 at 23:03
  • `byte b = Integer.decode("0xCA").byteValue();` –  Aug 09 '21 at 23:15

3 Answers3

2

Given the following string.

String s ="0xCA,0xFE,0xBA,0xBE,0x0,0x0,0x0,0x34,0x0,0xBB,0x1,0x0,0x35,0x6D,0x65,0x2F,0x6D";

You can do it as follows:

// remove the hex prefix and split on ','
String[] tokens = s.replace("0x","").split(",");

// allocate a byte array to hold the results
byte[] bytes = new byte[tokens.length];

//now parse to an int and assign to a byte.  Only the low order
// 8 bits will be assigned.
int i = 0;
for (String str : tokens) {
    bytes[i++] = (byte) Integer.parseInt(str,16);
}

for (byte b : bytes)
    System.out.print(b + " ");
}

Prints

-54 -2 -70 -66 0 0 0 52 0 -69 1 0 53 109 101 47 109 

Since some are greater 127 they will be printed as signed values.

WJS
  • 36,363
  • 4
  • 24
  • 39
  • Thanks you very much ill try this rn , but it's not possible to go from String "0xFE" to (byte)0xFE ? – Soros Aug 09 '21 at 23:12
  • Not directly. `0xFE` is an encoding when assigning a value to an int like `int a = 0xFE` or in binary like `int b = 0b1111; ` They are interpreted by the compiler. To parse a value in a particular radix it must be in the same format as when it was printed in that radix. `System.out.println(Integer.toString(199,16)` prints `c7` and that is also how it must be parsed. – WJS Aug 10 '21 at 00:11
1

Taking inspiration from @WJS' answer, here's another way, in this case using Integer.decode which can accept the integers in the 0x format you already have them:

String s ="0xCA,0xFE,0xBA,0xBE,0x0,0x0,0x0,0x34,0x0,0xBB,0x1,0x0,0x35,0x6D,0x65,0x2F,0x6D";

Arrays.stream(s.split(","))
        .map(Integer::decode)
        .map(Integer::byteValue)
        .forEach(b -> System.out.printf(" %d", b));
Edwin Dalorzo
  • 76,803
  • 25
  • 144
  • 205
  • 1
    Didn't know about decode. + 1. That could be useful for having a string of various encodings without having to worry about the prefix. – WJS Aug 10 '21 at 00:21
0

I see a problem right off the bat. 0xCA > byte.MAX_VALUE, thus giving it a value of -54 instead of the int value of 202. If this is what you want, then here is the code for it. If not, then just remove the byte cast and set x to an int instead.

    byte x = (byte)0;
    if(myByte.length() == "0xCA".length())
    x = (byte)((myByte.substring(0, 1).equals("0") ? 1 : -1) * (myByteVal(myByte.substring(2,3)) * 16 + myByteVal(myByte.substring(3,4))));
    else if(myByte.length() == "0x0".length())
    x = (byte)((myByte.substring(0, 1).equals("0") ? 1 : -1) * (myByteVal(myByte.substring(2,3))));

And the method I created for getting the value is here:

public static int myByteVal(String x) {
        x = x.toLowerCase();
        return x.equals("0") ? 0 : x.equals("1") ? 1 : x.equals("2") ? 2 : x.equals("3") ? 3 : x.equals("4") ? 4 : x.equals("5") ? 5 : x.equals("6") ? 6 : x.equals("7") ? 7 : x.equals("8") ? 8 : x.equals("9") ? 9 : x.equals("a") ? 10 : x.equals("b") ? 11 : x.equals("c") ? 12 : x.equals("d") ? 13 : x.equals("e") ? 14 : 15;
    }
xXMavhawkXx
  • 37
  • 1
  • 9