1

I'm reading a file from a FileList retrieved from HTMLInputElement and want to get the raw bytes out of File#arrayBuffer(). How do I do it?

import elemental2.core.ArrayBuffer;

public static byte[] toBytes(ArrayBuffer buffer) {
    // code in question
}

4
  • Is this an actual question? Is this actually a self-answer question? Do you have a question? Does your code not work? Commented Feb 8, 2023 at 11:43
  • Self-answer but better solutions are welcome Commented Feb 8, 2023 at 11:54
  • Consider editing your question to list the code that is causing a problem and a description of that problem. Commented Feb 11, 2023 at 16:26
  • 1
    @JohnH I've improved the question with a code skeleton Commented Feb 11, 2023 at 17:53

2 Answers 2

3

It turns out that as long as you don't look too closely at it, a JS Int8Array (and so a elemental2.core.Int8Array) behaves like you'd expect a GWT/Java byte[] to do - it will only contain values from -127 to 128. Unlike a "real" byte[], it will not correctly cast to byte[] and anything calling .getClass() or other Java methods on it will not work correctly either. It also can't be cast (by generics or explicitly) to byte[] either.

So if you need to treat the contents as a real Java array, you have to copy it first. Your answer will do what you want, but it might be more clearly correct to not "convert it from Double" along the way:

import elemental2.core.ArrayBuffer;
import elemental2.core.Int8Array;
import jsinterop.base.Js;

public static byte[] toBytes(ArrayBuffer buffer) {
    // Use uncheckedCast since we are outright lying to the compiler
    byte[] arr = Js.uncheckedCast(new Int8Array(buffer));
    byte[] result = new byte[arr.length];
    for (int i = 0; i < arr.length; i++) {
        result[i] = arr[i];
    }
    return result;
}

Your solution is also correct - a java.lang.Double in GWT and J2CL is exactly the same as a JS Number type, which is what your Int8Array is going to return when you query its values. The byteValue() call you're making will ask the compiler to make certain that the values are what is expected - it will truncate (probably via value & 0xFF?) the value, which should be cheap, but not entirely free.

Finally as long as you are just going to treat the resulting byte[] as a collection you can iterate, and won't be dealing with it in some way that the actual type will be checked, we can get away with not copying it at all:

import elemental2.core.ArrayBuffer;
import elemental2.core.Int8Array;
import jsinterop.base.Js;

public static byte[] toBytes(ArrayBuffer buffer) {
    byte[] result = Js.uncheckedCast(new Int8Array(buffer));
    return result;
}

This really is cheating though, and has other downsides, like if the original buffer is modified the array will be changed too, and vice versa. But it is very fast!

Sign up to request clarification or add additional context in comments.

Comments

1

Here's what I've got so far:

import elemental2.core.ArrayBuffer;
import elemental2.core.Int8Array;

public static byte[] toBytes(ArrayBuffer buffer) {
    Int8Array arr = new Int8Array(buffer);
    byte[] result = new byte[arr.length];
    for (int i = 0; i < arr.length; i++) {
        Double elem = arr.getAt(i);
        result[i] = elem.byteValue();
    }
    return result;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.