Skip to content

Instantly share code, notes, and snippets.

@72lions
Created January 14, 2013 09:22
Show Gist options
  • Star 58 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save 72lions/4528834 to your computer and use it in GitHub Desktop.
Save 72lions/4528834 to your computer and use it in GitHub Desktop.
Concatenates two ArrayBuffers
/**
* Creates a new Uint8Array based on two different ArrayBuffers
*
* @private
* @param {ArrayBuffers} buffer1 The first buffer.
* @param {ArrayBuffers} buffer2 The second buffer.
* @return {ArrayBuffers} The new ArrayBuffer created out of the two.
*/
var _appendBuffer = function(buffer1, buffer2) {
var tmp = new Uint8Array(buffer1.byteLength + buffer2.byteLength);
tmp.set(new Uint8Array(buffer1), 0);
tmp.set(new Uint8Array(buffer2), buffer1.byteLength);
return tmp.buffer;
};
@mapaiva
Copy link

mapaiva commented Aug 19, 2016

👍

@rico345100
Copy link

Awesome.

@amolpshinde07
Copy link

👍

@Ladvien
Copy link

Ladvien commented Jun 12, 2017

👍

@deanslamajr
Copy link

👍

@samccone
Copy link

👍

@apowers313
Copy link

In ES6+ there's an easier way using the "iterator" property of TypedArrays and the spread operator:

// create three example TypedArrays
// if you just have an ArrayBuffer called `ab` you can do `new Uint8Array(ab)`
var b1 = new Uint8Array([0x01, 0x02, 0x03]);
var b2 = new Uint8Array([0x04, 0x05, 0x06]);
var b3 = new Uint8Array([0x07, 0x08, 0x09]);

// combine all three arrays into a new array buffer
// if you need the ArrayBuffer instead of a TypedArray, it's at `combined.buffer
// NOTE: square brackets in the Uint8Array constructor -- Uint8Array([...])
var combined = new Uint8Array([
    ...b1,
    ...b2,
    ...b3
]);

// combined now contains:
// 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09

@tchakabam
Copy link

tchakabam commented Jul 24, 2018

Nullable version with correct jsdoc annotation. Allows to start-off from a null value accumulator and add up from there. Or to be able to concat with null which results in returning the same ArrayBuffer as input. Another option would be to create a plain copy here if you want to be "safe".

Also, I don't see any state here, no point this being "private" or any member of a class.

/**
 * Creates a new ArrayBuffer from concatenating two existing ones
 *
 * @param {ArrayBuffer | null} buffer1 The first buffer.
 * @param {ArrayBuffer | null} buffer2 The second buffer.
 * @return {ArrayBuffer | null} The new ArrayBuffer created out of the two.
 */
var concatArrayBuffers = function(buffer1, buffer2) {

  if (!buffer1) {
    return buffer2;
  } else if (!buffer2) {
    return buffer1;
  }

  var tmp = new Uint8Array(buffer1.byteLength + buffer2.byteLength);
  tmp.set(new Uint8Array(buffer1), 0);
  tmp.set(new Uint8Array(buffer2), buffer1.byteLength);
  return tmp.buffer;
};

@danakt
Copy link

danakt commented Nov 9, 2018

@apowers313 Unfortunately, your option will work slowly when high performance is needed. And typed arrays are used in such cases.

@reivash
Copy link

reivash commented Mar 29, 2019

👍

@saikishored
Copy link

Thank you. You saved my day :)

@jonathan-annett
Copy link

jonathan-annett commented Feb 24, 2020

 function concatArrayBuffers (bufs) {
                        var offset = 0;
                        var bytes = 0;
                        var bufs2=bufs.map(function(buf,total){
                            bytes += buf.byteLength;
                            return buf;
                        });
                        var buffer = new ArrayBuffer(bytes);
                        var store = new Uint8Array(buffer);
                        bufs2.forEach(function(buf){
                            store.set(new Uint8Array(buf.buffer||buf,buf.byteOffset),offset);
                            offset += buf.byteLength;
                        });
                        return buffer
                         
                    }
 var all_buffers = concatArrayBuffers([buffer1,buffer2,buffer3]);

@11zouzouzou
Copy link

good

@dtruffaut
Copy link

Great ! 👍👍👍

@zholmes1
Copy link

👍

@Krashdrive
Copy link

function concatArrayBuffers(...bufs){
	const result = new Uint8Array(bufs.reduce((totalSize, buf)=>totalSize+buf.byteLength,0));
	bufs.reduce((offset, buf)=>{
		result.set(buf,offset)
		return offset+buf.byteLength
	},0)
	return result.buffer
}

@martonlederer
Copy link

Literally saved my day. Best solution for performance

Copy link

ghost commented Jan 11, 2022

const concatenated = await new Blob([ buffer, buffer2 ]).arrayBuffer()

@Krashdrive
Copy link

I like Krashdrive's solution, simple and works flawlessly!

Thanks :)

@fujinxiang
Copy link

function concatArrayBuffers(...bufs){
	const result = new Uint8Array(bufs.reduce((totalSize, buf)=>totalSize+buf.byteLength,0));
	bufs.reduce((offset, buf)=>{
		result.set(buf,offset)
		return offset+buf.byteLength
	},0)
	return result.buffer
}

i meet error: Uncaught RangeError: offset is out of bounds

@tchakabam
Copy link

tchakabam commented Nov 21, 2022

@fujinxiang Works well for me here -> https://jsfiddle.net/fhsn0zg9/10/

Best create fiddle to demo what you mean? :)

@rashmimhatre100
Copy link

function concatArrayBuffers(...bufs){
	const result = new Uint8Array(bufs.reduce((totalSize, buf)=>totalSize+buf.byteLength,0));
	bufs.reduce((offset, buf)=>{
		result.set(buf,offset)
		return offset+buf.byteLength
	},0)
	return result.buffer
}

i meet error: Uncaught RangeError: offset is out of bounds

I am also getting error, "RangeError: offset is out of bounds".

@s1050613
Copy link

👍

@tchakabam
Copy link

tchakabam commented Mar 21, 2024

@rashmimhatre100 I am curious now :) Would you mind create a fiddle, and could you take a look at https://jsfiddle.net/fhsn0zg9/10/ ?
@fujinxiang

EDIT: realized you'd need to use this above func with Uint8Array wrapped inputs. That is a bit misleading, but the output will be a brand new allocated ArrayBuffer. See the example code on the fiddle.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment