Uint8Array
JavaScript で配列を使用している場合、最後の 4 バイトを取得してからそれを int に変換するにはどうすればよいですか? C# を使用すると、次のようになります。
int count = BitConverter.ToInt32(array, array.Length - 4);
JavaScript を使用してこれを行う不均等な方法はありますか?
Uint8Array
JavaScript で配列を使用している場合、最後の 4 バイトを取得してからそれを int に変換するにはどうすればよいですか? C# を使用すると、次のようになります。
int count = BitConverter.ToInt32(array, array.Length - 4);
JavaScript を使用してこれを行う不均等な方法はありますか?
基になるものにアクセスし、そのバイトのスライスをArrayBuffer
使用して新しいものを作成します。TypedArray
var u8 = new Uint8Array([1,2,3,4,5,6]); // original array
var u32bytes = u8.buffer.slice(-4); // last four bytes as a new `ArrayBuffer`
var uint = new Uint32Array(u32bytes)[0];
がバッファ全体をカバーしていない場合はTypedArray
、少し注意が必要ですが、それほど多くはありません。
var startbyte = u8.byteOffset + u8.byteLength - Uint32Array.BYTES_PER_ELEMENT;
var u32bytes = u8.buffer.slice(startbyte, startbyte + Uint32Array.BYTES_PER_ELEMENT);
これはどちらの場合でも機能します。
必要なバイトがデータ型の基になるバッファーのアライメント境界に収まる場合(たとえば、基になるバッファーのバイト4〜8の32ビット値が必要な場合)、バイトのコピーを回避し、バイトオフセットを指定するslice()
だけで済みます。 @Bergiの答えのように、ビューコンストラクタに。
以下は、必要なオフセットのスカラー値を取得する必要がある、非常に簡単にテストされた関数です。可能であればコピーを避けます。
function InvalidArgument(msg) {
this.message = msg | null;
}
function scalarValue(buf_or_view, byteOffset, type) {
var buffer, bufslice, view, sliceLength = type.BYTES_PER_ELEMENT;
if (buf_or_view instanceof ArrayBuffer) {
buffer = buf_or_view;
if (byteOffset < 0) {
byteOffset = buffer.byteLength - byteOffset;
}
} else if (buf_or_view.buffer instanceof ArrayBuffer) {
view = buf_or_view;
buffer = view.buffer;
if (byteOffset < 0) {
byteOffset = view.byteOffset + view.byteLength + byteOffset;
} else {
byteOffset = view.byteOffset + byteOffset;
}
return scalarValue(buffer, view.byteOffset + byteOffset, type);
} else {
throw new InvalidArgument('buf_or_view must be ArrayBuffer or have a .buffer property');
}
// assert buffer instanceof ArrayBuffer
// assert byteOffset > 0
// assert byteOffset relative to entire buffer
try {
// try in-place first
// only works if byteOffset % slicelength === 0
return (new type(buffer, byteOffset, 1))[0]
} catch (e) {
// if this doesn't work, we need to copy the bytes (slice them out)
bufslice = buffer.slice(byteOffset, byteOffset + sliceLength);
return (new type(bufslice, 0, 1))[0]
}
}
次のように使用します。
// positive or negative byte offset
// relative to beginning or end *of a view*
100992003 === scalarValueAs(u8, -4, Uint32Array)
// positive or negative byte offset
// relative to the beginning or end *of a buffer*
100992003 === scalarValue(u8.buffer, -4, Uint32Array)
例はありますか?これでうまくいくと思います:
var result = ((array[array.length - 1]) |
(array[array.length - 2] << 8) |
(array[array.length - 3] << 16) |
(array[array.length - 4] << 24));
少しエレガントではありませんが、エンディアンに基づいて手動で行うことができれば。
リトルエンディアン:
var count = 0;
// assuming the array has at least four elements
for(var i = array.length - 1; i >= array.length - 4; i--)
{
count = count << 8 + array[i];
}
ビッグエンディアン:
var count = 0;
// assuming the array has at least four elements
for(var i = array.length - 4; i <= array.length - 1 ; i++)
{
count = count << 8 + array[i];
}
これは、他のデータ長に拡張できます
編集:私のタイプミスを指摘してくれたデビッドに感謝します
同じ ArrayBuffer でビューを作成し、32 ビットの数値に直接アクセスする方が効率的です。Uint32Array
var uint8array = new Uint8Array([1,2,3,4,5,6,7,8]);
var uint32array = new Uint32Array(
uint8array.buffer,
uint8array.byteOffset + uint8array.byteLength - 4,
1 // 4Bytes long
);
return uint32array[0];
var a = Uint8Array(6)
a.set([1,2,8,0,0,1])
i1 = a[a.length-4];
i2 = a[a.length-3];
i3 = a[a.length-2];
i4 = a[a.length-1];
console.log(i1<<24 | i2<<16 | i3<<8 | i4);