如何将ArrayBuffer转换为byte[]?

huangapple go评论62阅读模式
英文:

How to convert ArrayBuffer to byte[]?

问题

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

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
}

答案1

得分: 3

事实证明,只要你不仔细查看,一个JS的Int8Array(以及elemental2.core.Int8Array)的行为就像你期望的GWT/Java的byte[]一样 - 它只包含从-127到128的值。与一个“真正的”byte[]不同,它不能正确地转换为byte[],并且在它上面调用.getClass()或其他Java方法的任何东西也不会正常工作。它也不能(通过泛型或显式地)转换为byte[]

所以,如果你需要把内容视为一个真正的Java数组,你首先必须将它复制一份。你的答案会得到你想要的结果,但在途中不“从Double转换它”可能会更清晰地正确:

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

public static byte[] toBytes(ArrayBuffer buffer) {
    // 使用uncheckedCast,因为我们在向编译器彻底撒谎
    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;
}

你的解决方案也是正确的 - 在GWT和J2CL中,java.lang.Double恰好与JS的Number类型相同,这就是当你查询Int8Array的值时会返回的类型。你正在调用的byteValue()方法将会要求编译器确保这些值是预期的 - 它将截断(可能是通过value & 0xFF?)这个值,这应该是便宜的,但并不完全免费。

最后,只要你只是将生成的byte[]视为一个可以迭代的集合,而不会以某种方式处理它,以至于需要检查实际类型,我们可以完全不复制它:

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

然而,这确实是在作弊,而且还有其他缺点,比如如果原始缓冲区被修改,数组也会被改变,反之亦然。但它非常快!

英文:

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 &lt; 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 &amp; 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!

答案2

得分: 1

以下是您要翻译的代码部分:

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;
}
英文:

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 &lt; arr.length; i++) {
        Double elem = arr.getAt(i);
        result[i] = elem.byteValue();
    }
    return result;
}

huangapple
  • 本文由 发表于 2023年2月8日 19:40:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/75385273.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定