NodeJS 바이너리 버퍼를 JavaScript ArrayBuffer로 어떻게 변환 할 수 있습니까?
Array
입니다. 따라서 많은 수레를 저장하려면 Float32Array
4 바이트가 필요한 곳 이 필요 합니다. 그리고 부동 소수점을 파일로 빠르게 Buffer
직렬화하려면 JSON으로 직렬화하는 데 시간이 오래 걸리기 때문에 가 필요합니다 .
NodeJS 바이너리 버퍼를 JavaScript ArrayBuffer로 어떻게 변환 할 수 있습니까?
Array
입니다. 따라서 많은 수레를 저장하려면 Float32Array
4 바이트가 필요한 곳 이 필요 합니다. 그리고 부동 소수점을 파일로 빠르게 Buffer
직렬화하려면 JSON으로 직렬화하는 데 시간이 오래 걸리기 때문에 가 필요합니다 .
답변:
의 인스턴스 Buffer
도Uint8Array
node.js 4.x 이상의 인스턴스입니다 . 따라서 가장 효율적인 솔루션은 https://stackoverflow.com/a/31394257/1375574에 따라 buf.buffer
속성에 직접 액세스하는 것 입니다. Buffer 생성자는 다른 방향으로 이동해야하는 경우 ArrayBufferView 인수도 사용합니다.
이렇게하면 복사본이 만들어지지 않습니다. 즉, ArrayBufferView에 쓰면 원래 Buffer 인스턴스에 쓰입니다.
버퍼에서 어레이 버퍼로 :
function toArrayBuffer(buf) {
var ab = new ArrayBuffer(buf.length);
var view = new Uint8Array(ab);
for (var i = 0; i < buf.length; ++i) {
view[i] = buf[i];
}
return ab;
}
ArrayBuffer에서 버퍼로 :
function toBuffer(ab) {
var buf = Buffer.alloc(ab.byteLength);
var view = new Uint8Array(ab);
for (var i = 0; i < buf.length; ++i) {
buf[i] = view[i];
}
return buf;
}
size&0xfffffffe
32 비트 정수를 복사 한 다음, 1 바이트가 남아 있으면 8 비트 정수를 복사하고, 2 바이트이면 16 비트 정수를 복사하고, 3 바이트이면 16 비트 및 8 비트 정수를 복사하십시오.
ab
반환됩니까? 아무런 작업이 ab
없습니까? 나는 항상 {}
결과를 얻는다 .
slice()
방법은 ArrayBuffer
내용이 ArrayBuffer
시작부터 포함, 끝까지 의이 바이트 의 사본 인 새로운 것을 반환합니다 .' - MDNArrayBuffer.prototype.slice()
Buffer
는 Uint8Array
s이므로 백업 영역을 슬라이스 (복사)하면 ArrayBuffer
됩니다.
// Original Buffer
let b = Buffer.alloc(512);
// Slice (copy) its segment of the underlying ArrayBuffer
let ab = b.buffer.slice(b.byteOffset, b.byteOffset + b.byteLength);
slice
오프셋 물건이되어 필요한 작은 때문에 Buffer
의 (기본적으로 이하 4 KB, 절반 풀 크기가 ) 공유에 전망 할 수있다 ArrayBuffer
. 슬라이스하지 않으면 ArrayBuffer
다른 데이터를 포함하는 데이터로 끝날 수 있습니다 Buffer
. 문서의 설명을 참조하십시오 .
궁극적으로가 필요한 경우 TypedArray
데이터를 복사하지 않고 생성 할 수 있습니다.
// Create a new view of the ArrayBuffer without copying
let ui32 = new Uint32Array(b.buffer, b.byteOffset, b.byteLength / Uint32Array.BYTES_PER_ELEMENT);
O (n) 시간에 실행되는 Martin Thomson의 답변을 사용하십시오 . (최적화에 대한 그의 답변에 대한 의견에 대한 내 답변을 참조하십시오. DataView 사용은 느립니다. 바이트를 뒤집어 야하는 경우에도 더 빠른 방법이 있습니다.)
https://www.npmjs.com/package/memcpy 를 사용 하여 어느 방향 으로든 이동할 수 있습니다 (Buffer to ArrayBuffer 및 back). 여기에 게시 된 다른 답변보다 빠르며 잘 작성된 라이브러리입니다. (참조의에게 포크를 ngossen 필요 3.x를 iojs을 통해 노드 0.12 이 ).
.byteLength
및 .byteOffset
문서화?
var ab = b.buffer.slice(b.byteOffset, b.byteOffset + b.byteLength);
내 하루를 구했다
"ArrayBuffer에서 버퍼로"는 다음과 같이 수행 할 수 있습니다.
var buffer = Buffer.from( new Uint8Array(ab) );
작성하는 더 빠른 방법
var arrayBuffer = new Uint8Array(nodeBuffer).buffer;
그러나 이는 1024 개의 요소가있는 버퍼에서 제안 된 toArrayBuffer 함수보다 약 4 배 느리게 실행되는 것으로 보입니다.
Buffer
인스턴스도 인스턴스 이기 때문에 작동합니다 Uint8Array
. 더 낮은 Node.js 버전의 경우 toArrayBuffer
함수 를 구현해야 합니다.
Buffer
는 을 살펴 보기 위한 보기 일뿐 ArrayBuffer
입니다.A는 Buffer
, 사실,이며 FastBuffer
, 이는 extends
(로부터 상속)를 Uint8Array
옥텟 단위 인 도 실제 메모리, 중 ( "부분적인 접근은") ArrayBuffer
.
/lib/buffer.js#L65-L73
class FastBuffer extends Uint8Array {
constructor(arg1, arg2, arg3) {
super(arg1, arg2, arg3);
}
}
FastBuffer.prototype.constructor = Buffer;
internalBuffer.FastBuffer = FastBuffer;
Buffer.prototype = FastBuffer.prototype;
ArrayBuffer
와 보기 의 크기 는 다를 수 있습니다.Buffer.from(arrayBuffer[, byteOffset[, length]])
.을 사용하면 기본 및 뷰의 위치와 크기 를 지정하여을 Buffer.from(arrayBuffer[, byteOffset[, length]])
만들 수 있습니다 .Buffer
ArrayBuffer
const test_buffer = Buffer.from(new ArrayBuffer(50), 40, 10);
console.info(test_buffer.buffer.byteLength); // 50; the size of the memory.
console.info(test_buffer.length); // 10; the size of the view.
FastBuffer
의 메모리 할당.크기에 따라 두 가지 다른 방식으로 메모리를 할당합니다.
ArrayBuffer
필요한 메모리에 정확히 맞는 전용 을 만듭니다 ./lib/buffer.js#L306-L320
function allocate(size) {
if (size <= 0) {
return new FastBuffer();
}
if (size < (Buffer.poolSize >>> 1)) {
if (size > (poolSize - poolOffset))
createPool();
var b = new FastBuffer(allocPool, poolOffset, size);
poolOffset += size;
alignPool();
return b;
} else {
return createUnsafeBuffer(size);
}
}
📜 Node.js를 9.4.0/lib/buffer.js#L98-L100
function createUnsafeBuffer(size) {
return new FastBuffer(createUnsafeArrayBuffer(size));
}
메모리 풀을 고정 된 크기이다 사전 할당 을위한 작은 크기의 메모리 청크를 유지하기위한 메모리 블록 Buffer
들. 이를 사용하면 작은 크기의 메모리 청크가 단단히 고정되므로 작은 크기의 메모리 청크 를 별도로 관리 (할당 및 할당 해제)하여 발생 하는 조각화를 방지 할 수 있습니다.
이 경우 메모리 풀 ArrayBuffer
의 크기는 기본적으로 8KiB이며에 지정되어 Buffer.poolSize
있습니다. a에 작은 크기의 메모리 청크를 제공하려는 Buffer
경우 마지막 메모리 풀에이를 처리 할 수있는 충분한 메모리가 있는지 확인합니다. 그렇다면 메모리 풀의 주어진 부분 청크 Buffer
를 "보는" 것을 생성하고, 그렇지 않으면 새로운 메모리 풀을 생성합니다.
의 기본 ArrayBuffer
에 액세스 할 수 있습니다 Buffer
. Buffer
의 buffer
재산 에서 상속 (Uint8Array
)를 보유하고 있습니다. "작은" 의 속성은입니다 전체 메모리 풀을 나타냅니다. 따라서이 경우에는 및의 크기 가 다릅니다. Buffer
buffer
ArrayBuffer
ArrayBuffer
Buffer
const zero_sized_buffer = Buffer.allocUnsafe(0);
const small_buffer = Buffer.from([0xC0, 0xFF, 0xEE]);
const big_buffer = Buffer.allocUnsafe(Buffer.poolSize >>> 1);
// A `Buffer`'s `length` property holds the size, in octets, of the view.
// An `ArrayBuffer`'s `byteLength` property holds the size, in octets, of its data.
console.info(zero_sized_buffer.length); /// 0; the view's size.
console.info(zero_sized_buffer.buffer.byteLength); /// 0; the memory..'s size.
console.info(Buffer.poolSize); /// 8192; a memory pool's size.
console.info(small_buffer.length); /// 3; the view's size.
console.info(small_buffer.buffer.byteLength); /// 8192; the memory pool's size.
console.info(Buffer.poolSize); /// 8192; a memory pool's size.
console.info(big_buffer.length); /// 4096; the view's size.
console.info(big_buffer.buffer.byteLength); /// 4096; the memory's size.
console.info(Buffer.poolSize); /// 8192; a memory pool's size.
의 ArrayBuffer
크기는 고정되어 있으므로 부품을 복사하여 추출해야합니다. 이를 위해 우리는 Buffer
의 byteOffset
property 와 length
property 를 사용합니다.Uint8Array
및 방법 의 일부의 사본을 만든다 . 여기에서 -ing 방법은 @ZachB 에서 영감을 얻었습니다 .ArrayBuffer.prototype.slice
ArrayBuffer
slice()
const test_buffer = Buffer.from(new ArrayBuffer(10));
const zero_sized_buffer = Buffer.allocUnsafe(0);
const small_buffer = Buffer.from([0xC0, 0xFF, 0xEE]);
const big_buffer = Buffer.allocUnsafe(Buffer.poolSize >>> 1);
function extract_arraybuffer(buf)
{
// You may use the `byteLength` property instead of the `length` one.
return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.length);
}
// A copy -
const test_arraybuffer = extract_arraybuffer(test_buffer); // of the memory.
const zero_sized_arraybuffer = extract_arraybuffer(zero_sized_buffer); // of the... void.
const small_arraybuffer = extract_arraybuffer(small_buffer); // of the part of the memory.
const big_arraybuffer = extract_arraybuffer(big_buffer); // of the memory.
console.info(test_arraybuffer.byteLength); // 10
console.info(zero_sized_arraybuffer.byteLength); // 0
console.info(small_arraybuffer.byteLength); // 3
console.info(big_arraybuffer.byteLength); // 4096
결과를 읽기 전용으로 사용하거나 입력을 수정해도 괜찮은 경우 Buffer
내용 불필요한 메모리 복사를 피할 수 있습니다.
const test_buffer = Buffer.from(new ArrayBuffer(10));
const zero_sized_buffer = Buffer.allocUnsafe(0);
const small_buffer = Buffer.from([0xC0, 0xFF, 0xEE]);
const big_buffer = Buffer.allocUnsafe(Buffer.poolSize >>> 1);
function obtain_arraybuffer(buf)
{
if(buf.length === buf.buffer.byteLength)
{
return buf.buffer;
} // else:
// You may use the `byteLength` property instead of the `length` one.
return buf.subarray(0, buf.length);
}
// Its underlying `ArrayBuffer`.
const test_arraybuffer = obtain_arraybuffer(test_buffer);
// Just a zero-sized `ArrayBuffer`.
const zero_sized_arraybuffer = obtain_arraybuffer(zero_sized_buffer);
// A copy of the part of the memory.
const small_arraybuffer = obtain_arraybuffer(small_buffer);
// Its underlying `ArrayBuffer`.
const big_arraybuffer = obtain_arraybuffer(big_buffer);
console.info(test_arraybuffer.byteLength); // 10
console.info(zero_sized_arraybuffer.byteLength); // 0
console.info(small_arraybuffer.byteLength); // 3
console.info(big_arraybuffer.byteLength); // 4096
obtain_arraybuffer
: buf.buffer.subarray
존재하지 않는 것 같습니다. buf.buffer.slice
여기에 있었 습니까 ?
ArrayBuffer.prototype.slice
하여 나중에 수정했습니다 Uint8Array.prototype.subarray
. 아, 그리고 내가 잘못했다. 그 당시에는 약간 혼란 스러웠을 것입니다. 당신 덕분에 지금은 모두 좋습니다.
다음과 같은 우수한 npm 패키지를 사용하십시오 to-arraybuffer
.
또는 직접 구현할 수 있습니다. 버퍼가 호출 buf
되면 다음을 수행하십시오.
buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength)
당신은 ArrayBuffer
유형으로 생각할 수 있습니다 Buffer
.
은 ArrayBuffer
그러므로 항상 유형 (소위 "배열 버퍼보기")를 필요로한다. 일반적으로 배열 버퍼보기 의 유형은 Uint8Array
또는 Uint16Array
입니다.
Renato Mangini 의 ArrayBuffer와 String 간의 변환 에 대한 좋은 기사가 있습니다 .
코드 예제 (Node.js의 경우)에서 필수 부분을 요약했습니다. 또한 typed ArrayBuffer
와 untyped 사이를 변환하는 방법을 보여줍니다 Buffer
.
function stringToArrayBuffer(string) {
const arrayBuffer = new ArrayBuffer(string.length);
const arrayBufferView = new Uint8Array(arrayBuffer);
for (let i = 0; i < string.length; i++) {
arrayBufferView[i] = string.charCodeAt(i);
}
return arrayBuffer;
}
function arrayBufferToString(buffer) {
return String.fromCharCode.apply(null, new Uint8Array(buffer));
}
const helloWorld = stringToArrayBuffer('Hello, World!'); // "ArrayBuffer" (Uint8Array)
const encodedString = new Buffer(helloWorld).toString('base64'); // "string"
const decodedBuffer = Buffer.from(encodedString, 'base64'); // "Buffer"
const decodedArrayBuffer = new Uint8Array(decodedBuffer).buffer; // "ArrayBuffer" (Uint8Array)
console.log(arrayBufferToString(decodedArrayBuffer)); // prints "Hello, World!"
Float64Array에 대해 위의 시도했지만 작동하지 않았습니다.
나는 실제로 데이터가 올바른 덩어리로 뷰를 'INTO'해야한다는 것을 깨달았습니다. 이는 소스 버퍼에서 한 번에 8 바이트를 읽는 것을 의미합니다.
어쨌든 이것은 내가 끝내는 것입니다 ...
var buff = new Buffer("40100000000000004014000000000000", "hex");
var ab = new ArrayBuffer(buff.length);
var view = new Float64Array(ab);
var viewIndex = 0;
for (var bufferIndex=0;bufferIndex<buff.length;bufferIndex=bufferIndex+8) {
view[viewIndex] = buff.readDoubleLE(bufferIndex);
viewIndex++;
}
Buffer.read*
방법은, 모든 느리다.
이 프록시는 복사본없이 버퍼를 TypedArray 중 하나로 노출합니다. :
https://www.npmjs.com/package/node-buffer-as-typedarray
LE에서만 작동하지만 BE로 쉽게 이식 할 수 있습니다. 또한 실제로 이것이 얼마나 효율적인지 테스트하지 않아도됩니다.
이제 이것을 위해 매우 유용한 npm 패키지가 있습니다 : buffer
https://github.com/feross/buffer
노드의 버퍼 API와 100 % 동일한 API를 제공하고 다음을 허용합니다.
그리고 몇 가지 더.
이미 노드를 버전 5.0.0으로 업데이트했으며 다음과 같이 작업합니다.
function toArrayBuffer(buffer){
var array = [];
var json = buffer.toJSON();
var list = json.data
for(var key in list){
array.push(fixcode(list[key].toString(16)))
}
function fixcode(key){
if(key.length==1){
return '0'+key.toUpperCase()
}else{
return key.toUpperCase()
}
}
return array
}
vhd 디스크 이미지를 확인하는 데 사용합니다.
toArrayBuffer(new Buffer([1,2,3]))
-> ['01', '02', '03']
-정수 / 바이트가 아닌 문자열 배열을 반환합니다.