如果我在JavaScript中有一個Uint8Array
數組,我將如何得到最後四個字節,然後將其轉換爲int?使用C#我會做這樣的事情:如何將數組中的最後4個字節轉換爲整數?
int count = BitConverter.ToInt32(array, array.Length - 4);
是否有不等同的方式來使用JavaScript來做到這一點?
如果我在JavaScript中有一個Uint8Array
數組,我將如何得到最後四個字節,然後將其轉換爲int?使用C#我會做這樣的事情:如何將數組中的最後4個字節轉換爲整數?
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()
並且只給視圖構造函數提供一個byteoffset,就像在@ 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)
+1,非常好。然而,如果'u8'是一個緩衝區上有偏移量的視圖,它就不會工作,這需要特殊處理。 – Bergi 2013-02-19 17:45:29
你有個例子嗎?我認爲這會做到這一點:
var result = ((array[array.length - 1]) |
(array[array.length - 2] << 8) |
(array[array.length - 3] << 16) |
(array[array.length - 4] << 24));
使用'[255,255,255,255]'會因某種原因使用此代碼而產生'-1'。 – Jespertheend 2016-07-02 21:31:40
@Jespertheend結果是'-1',因爲它的簽名。添加一個無符號右移運算符'>>> 0'將結果轉換爲無符號值('4294967295')。 – SammieFox 2017-09-04 15:22:40
嗯,這是有道理的。 – Jespertheend 2017-09-04 19:01:27
有點不雅,但如果你可以做到手動根據endianess。
小尾數:
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];
}
這可以擴展到其他數據長度
編輯:感謝David指出我的錯別字
應該是'.length'而不是'.Length' – 0x499602D2 2013-02-19 17:15:11
創建一個Uint32Array
應該更有效率在同一ArrayBuffer和直接訪問32位數字:
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];
不幸的是,似乎你不能在同一個緩衝區上創建一個不同類型的新視圖,除非第二個參數是新視圖長度的倍數。例如。在一個8字節的緩衝區上,儘管它看起來像是一個任意的限制,但仍然失敗:'new Uint32Array(buffer,2,1)' – 2013-02-19 17:48:45
@FrancisAvila:感謝提示,如果是非4Byte多重緩衝區,切片。我現在修復了我的代碼(上述工作),我忘記了我需要從byteLength中減去* 4 *以獲得32位: -/ – Bergi 2013-02-19 18:00:42
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);
如今,如果你可以用IE 11+/Chrome 49+/Firefox 50+生活,那麼你可以使用DataView使您的生活幾乎一樣容易,因爲在C#:
var u8array = new Uint8Array([0xFF, 0xFF, 0xFF, 0xFF]); // -1
var view = new DataView(u8array.buffer)
console.log("result:" + view.getInt32());
@ cIph3r:[Yes](https://developer.mozilla。org/en-US/docs/JavaScript/Typed_arrays/Uint8Array) – Bergi 2013-02-19 17:07:41
@Bergi 好的,但是這隻適用於firefox – cIph3r 2013-02-19 17:10:08
@ clph3r,[和Chrome和Safari,Opera和IE10和Android](http:///caniuse.com/#feat=typedarrays).... – 2013-02-19 17:22:11