I'd like to read a binary file with a few 32 bit float values at byte offset 31.
Unfortunately, new Float32Array(buffer, 31, 6);
does not work. An offset of 32 instead of 31 works but I need 31.
According to this page, offset has to be a multiple of the element size, 4 in this case.
I'm interested in the reason behind this behaviour. Why does it matter where the view starts?
The best workaround I found thus far has not made it into gecko yet so I can't use it.
Do I realy have to cut and copy the byte values into a new array to get my float values?
I'd like to read a binary file with a few 32 bit float values at byte offset 31.
Unfortunately, new Float32Array(buffer, 31, 6);
does not work. An offset of 32 instead of 31 works but I need 31.
According to this page, offset has to be a multiple of the element size, 4 in this case.
I'm interested in the reason behind this behaviour. Why does it matter where the view starts?
The best workaround I found thus far has not made it into gecko yet so I can't use it.
Do I realy have to cut and copy the byte values into a new array to get my float values?
Share Improve this question edited Sep 10, 2011 at 13:50 pimvdb 155k80 gold badges311 silver badges356 bronze badges asked Sep 10, 2011 at 13:45 MarkusMarkus 2,2222 gold badges24 silver badges39 bronze badges 3- I suspect it's just a matter of expecting multi-byte values to be properly aligned in memory. edit - having the proposed ".slice()" method on ArrayBuffer would be one good workaround, because that'd let you copy odd-aligned bytes into a new well-aligned buffer. – Pointy Commented Sep 10, 2011 at 14:06
- @Pointy I've extended ArrayBuffer with a subarray function: ArrayBuffer.prototype.subarray = function(offset, length){ var sub = new ArrayBuffer(length); var subView = new Int8Array(sub); var thisView = new Int8Array(this); for(var i = 0; i < length; i++ ){ subView[i] = thisView[offset+i]; } return sub; } – Markus Commented Sep 10, 2011 at 14:16
- OK yes that's probably what ".slice()" would do too :-) It seems like an awkward set of APIs to work with; I have only recently started reading about it all. – Pointy Commented Sep 10, 2011 at 14:21
3 Answers
Reset to default 9I'm interested in the reason behind this behaviour. Why does it matter where the view starts?
Some architectures do not allow unaligned word accesses, and there are performance penalties on architectures that do allow it such as x86 (though some instructions must be aligned).
Do I really have to cut and copy the byte values into a new array to get my float values?
Yes, just like Markus' example you should create a new ArrayBuffer
with a UInt8Array
view and a Float32Array
view for a read_buffer
(copy with UInt8Array
view and interpret from Float32Array
view). Then you can read from your data with a UInt8Array
, copy that into your read_buffer
view and then interpret using the Float32Array
. It's quite a seamless process.
DataView.getFloat32() would be the best way to do this. DataView is designed for packed data and allows unaligned access to the data in an ArrayBuffer so you can pass in odd offsets like 31.
You can use slice
to get a new ArrayBuffer whose contents are a copy of this ArrayBuffer's bytes from begin, inclusive, up to end
const buffer = new ArrayBuffer(250);
const list = buffer.slice(10); // index [11,250]
const nums = new Int32Array(list, 0, 60);