Javascript 复制 ArrayBuffer 对象最直接的方法是什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10100798/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What's the most straightforward way to copy an ArrayBuffer object?
提问by zneak
I'm working with ArrayBuffer
objects, and I would like to duplicate them. While this is rather easy with actual pointers and memcpy
, I couldn't find any straightforward way to do it in Javascript.
我正在处理ArrayBuffer
对象,我想复制它们。虽然这对于实际的指针和 来说相当容易memcpy
,但我在 Javascript 中找不到任何直接的方法。
Right now, this is how I copy my ArrayBuffers
:
现在,这就是我复制我的方式ArrayBuffers
:
function copy(buffer)
{
var bytes = new Uint8Array(buffer);
var output = new ArrayBuffer(buffer.byteLength);
var outputBytes = new Uint8Array(output);
for (var i = 0; i < bytes.length; i++)
outputBytes[i] = bytes[i];
return output;
}
Is there a prettier way?
有没有更漂亮的方法?
回答by Gleno
I prefer the following method
我更喜欢下面的方法
function copy(src) {
var dst = new ArrayBuffer(src.byteLength);
new Uint8Array(dst).set(new Uint8Array(src));
return dst;
}
回答by chuckj
ArrayBuffer
is supposed to support slice
(http://www.khronos.org/registry/typedarray/specs/latest/) so you can try,
ArrayBuffer
应该支持slice
(http://www.khronos.org/registry/typedarray/specs/latest/) 所以你可以试试,
buffer.slice(0);
which works in Chrome 18 but not Firefox 10 or 11. As for Firefox, you need to copy it manually. You can monkey patch the slice()
in Firefox because the Chrome slice()
will outperform a manual copy. This would look something like,
它适用于 Chrome 18 但不适用于 Firefox 10 或 11。至于 Firefox,您需要手动复制它。您可以slice()
在 Firefox 中打补丁,因为 Chromeslice()
会胜过手动复制。这看起来像,
if (!ArrayBuffer.prototype.slice)
ArrayBuffer.prototype.slice = function (start, end) {
var that = new Uint8Array(this);
if (end == undefined) end = that.length;
var result = new ArrayBuffer(end - start);
var resultArray = new Uint8Array(result);
for (var i = 0; i < resultArray.length; i++)
resultArray[i] = that[i + start];
return result;
}
Then you can call,
然后就可以打电话了
buffer.slice(0);
to copy the array in both Chrome and Firefox.
在 Chrome 和 Firefox 中复制数组。
回答by Andrew
It appears that simply passing in the source dataview performs a copy:
似乎只需传入源数据视图即可执行复制:
var a = new Uint8Array([2,3,4,5]);
var b = new Uint8Array(a);
a[0] = 6;
console.log(a); // [6, 3, 4, 5]
console.log(b); // [2, 3, 4, 5]
Tested in FF 33 and Chrome 36.
在 FF 33 和 Chrome 36 中测试。
回答by Orwellophile
Hmmm... if it's the Uint8Array you want to slice (which logically, it should be), this may work.
嗯...如果它是您想要切片的 Uint8Array(从逻辑上讲,它应该是),这可能会起作用。
if (!Uint8Array.prototype.slice && 'subarray' in Uint8Array.prototype)
Uint8Array.prototype.slice = Uint8Array.prototype.subarray;
回答by xmichaelx
Faster and slightly more complicated version of chuckj's answer. Should use ~8x less copy operations on large Typed Arrays. Basically we copy as much 8-byte chunks as possible and then copy the remaining 0-7 bytes. This is especially useful in current version of IE, since it doesn't have slice method implemented for ArrayBuffer.
查克杰答案的更快且稍微复杂的版本。应该对大型类型化数组使用约 8 倍的复制操作。基本上我们复制尽可能多的 8 字节块,然后复制剩余的 0-7 字节。这在当前版本的 IE 中特别有用,因为它没有为 ArrayBuffer 实现切片方法。
if (!ArrayBuffer.prototype.slice)
ArrayBuffer.prototype.slice = function (start, end) {
if (end == undefined) end = that.length;
var length = end - start;
var lengthDouble = Math.floor(length / Float64Array.BYTES_PER_ELEMENT);
// ArrayBuffer that will be returned
var result = new ArrayBuffer(length);
var that = new Float64Array(this, start, lengthDouble)
var resultArray = new Float64Array(result, 0, lengthDouble);
for (var i = 0; i < resultArray.length; i++)
resultArray[i] = that[i];
// copying over the remaining bytes
that = new Uint8Array(this, start + lengthDouble * Float64Array.BYTES_PER_ELEMENT)
resultArray = new Uint8Array(result, lengthDouble * Float64Array.BYTES_PER_ELEMENT);
for (var i = 0; i < resultArray.length; i++)
resultArray[i] = that[i];
return result;
}
回答by Zibri
In some cases (like webaudio Audiobuffers) you only have a reference to the 2 arrays.
So if you have array1 as a float32Array and array2 as a float32Array,
you must do an element by element copy.
在某些情况下(如 webaudio Audiobuffers),您只有对 2 个数组的引用。
因此,如果您将 array1 作为 float32Array 并将 array2 作为 float32Array,则
必须逐个元素复制。
To do so you can use different methods.
为此,您可以使用不同的方法。
var ib=z.inputBuffer.getChannelData(0);
var ob=z.outputBuffer.getChannelData(0);
this
这个
ib.forEach((chd,i)=>ob[i]=chd);
or this nicer and probably faster
或者这个更好,可能更快
ob.set(ib);
That's because Array.set populates an existing array with multiple data (even from another array)
那是因为 Array.set 用多个数据(甚至来自另一个数组)填充现有数组