5

Uint8ArrayJavaScript で配列を使用している場合、最後の 4 バイトを取得してからそれを int に変換するにはどうすればよいですか? C# を使用すると、次のようになります。

int count = BitConverter.ToInt32(array, array.Length - 4);

JavaScript を使用してこれを行う不均等な方法はありますか?

4

8 に答える 8

9

基になるものにアクセスし、そのバイトのスライスを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)
于 2013-02-19T17:20:34.147 に答える
7

例はありますか?これでうまくいくと思います:

var result = ((array[array.length - 1]) | 
              (array[array.length - 2] << 8) | 
              (array[array.length - 3] << 16) | 
              (array[array.length - 4] << 24));
于 2013-02-19T17:11:20.527 に答える
4

少しエレガントではありませんが、エンディアンに基づいて手動で行うことができれば。

リトルエンディアン:

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

これは、他のデータ長に拡張できます

編集:私のタイプミスを指摘してくれたデビッドに感謝します

于 2013-02-19T17:12:44.830 に答える
1

同じ 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];
于 2013-02-19T17:14:01.897 に答える
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);
于 2013-02-19T17:22:18.363 に答える