From Liu Yan (@ Liu Yan-jimliu)
Website: http://jimliu.net/2015/09/26/a-brief-look-at-binary-ops-in-js/
The origins of this blog are discussed in an article on Div.io , "The JavaScript array you don't know" by little beard .
Because with the popularity of XHR2 and modern browsers, processing binary in the browser is no longer the same as the past, with new technologies such as CANVAS/WEBGL gradually began to enter the public view, will also use some byte array or 16-bit, 8-bit integer and other things. In the 4.0 release of node. js, the bottom of the buffer was implemented with a more JS standard, Uint8Array Browser and node. JS again to the same target near a little bit, so for JS processing binary, I would like to write this article as an introductory nature of the journal, convenient for some of the binary processing does not understand the students quickly get started, although in the front-end field used not much, but also can be used as leisure gossip.
The representation of binary data in JS program
Almost all computer architectures in the world today are in bytes (byte) as the basic unit of binary data (note: not the smallest unit), so the binary is often in the form of byte arrays in the program. In C #, for example, there is byte[] no type in standard C, byte but the typedef byte unsigned char effect is the same by defining the alias.
JS Design at the beginning does not seem to want to deal with binary things, plus the type of extreme weakening, the concept of the byte can be said to be very very vague. If you want to express an array of bytes, it seems that only a normal array can be represented.
HTML5 system introduced a lot of new things, such as XHR2, is can upload or download binary content, and the matching thing is JS in the Arraybuffer and typed array.
ArrayBufferis a fixed-length sequence of bytes, you can new ArrayBuffer(length) get a space through, or use the methods described below from XHR2 and other ways to obtain. Because internal implementations are not the same as arrays, ArrayBuffer they are usually contiguous memory (note that this is only a rule of thumb, not a specification or a document), so it is much faster than the array in JS for high-density access operations (but it does not have to be used as a simple substitute for array). If you look at the heap Snapshot with Chrome's profile tool, you'll find that Arraybuffer is listed as a separate category, perhaps with its memory allocations and layouts that differ from the array and other JS objects.
ArrayBufferis not directly accessible, so you need to use the typed Array. The Typed array is a group of array-like types for a specific set of data types, including
Int8array A 8-bit signed integer, similar to the Charuint8array charuint8clampedarray 8-bit unsigned integer inside C, Similar to Uint8, but not as much as overflow handling Int16array These types are not wordy Uint16arrayint32arrayuint32arrayfloat32arrayfloat64array
Multipleviews on the same data Typed array is behind a, that is, the fact that there is a ArrayBuffer real figure ArrayBuffer , and the Typed array just gives you a certain type of read-write interface , in the words of the MDN, called
For a chestnut, if we have a ArrayBuffer name of buffer (without considering how to construct this test data), the contents are as follows:
01 02 03 04 05 06 07 08
That is, it has 8 bytes, which we use to construct, and Uint8Array Uint16Array then we Uint32Array can get
var New // length is 8 var New // length is 4 var New // length is 2
Their contents were
[1, 2, 3, 4, 5, 6, 7, 8] [513, 1027, 1541, 2055][67305985, 134678021]
It's not hard to understand.
As you can see, it would be convenient to use it if you were to manually construct the above test data ArrayBuffer Uint8Array (er, actually this is one of my most commonly used typed arrays).
If you use the same ArrayBuffer build signed integer type, you may get different results because of an integer overflow, the above example does not come across, if you are interested, you can try it yourself. Therefore, using the typed array can also be used to convert signed and unsigned numbers.
If you've ever used canvas getImageData/putImageData , you'll find that it gives you a Uint8ClampedArray lot faster than JS's native array, making it possible to do high-speed pixel manipulation on canvas.
However, one of the most important concepts is that theTyped array does not store any data directly, and all operations that read and write to the Typed array will eventually be implemented into ArrayBuffer the body behind it. ArrayBuffer is the real raw bytes, and the typed array is just an action window/Operation view.
Obtaining binary data
Nodejs there first, hold the table. How do I get binary data from a Web page? There are 3 common approaches, 1 are through XMLHttpRequest 2 , and 2 are through File and a Blob set of related interfaces.
by XMLHttpRequest 2
The interface of XHR2 is almost the same as XHR, and when it is developed xhr.responseType = ‘arraybuffer‘ , it is possible to obtain the request result in the callback of successful data acquisition xhr.response ArrayBuffer , and then you can construct various typed array to access it according to your wishes.
responseTypeYou can also have a blob value that can be used to xhr.response get a Blob object.
Through file and blob
The HTML5 provides a richer manipulation of the form's file controls, which <input type="file" /> can be obtained by input DOM objects, and, .files FileList of course, only a single file control is provided by the browser, so there is only one document object. In addition, by dragging, clipboard, etc. can also be obtained File or Blob .
FileInherited Blob , and provided name , lastModifiedDate such as the underlying metadata, but still a deep encapsulation, cannot be directly obtained to its binary.
Blobis Binary large object the abbreviation, and ArrayBuffer the difference is that besides raw bytes it also provides MIME type as metadata. But it is still not directly read and written.
At this time need to use FileReader help. FileReaderprovides a set Blob of methods that are used to read to a more practical type
Readasarraybuffer () readasbinarystring () Readasdataurl () Readastext ()
For example:
var file = get_file_some_how (); var New function(e) { / / Read result // Readasarraybuffer
What can I do? Local previews (even canvas-based edits) before the sample upload can be implemented.
BlobOther construction methods are many and miscellaneous, here is not to move around the document.
Consumption of binary data
What is consumption? Perhaps the most common way is to post the binary data directly to the server via the XHR2 file.
I recommend using Formdata to construct post data here. Because in the service end of the time will be more easy, specific interested can go to find other people's example.
Although the direct submission ArrayBuffer is also possible, but this time the server receives the post body will be a large group, inconvenient to use. If you want FormData to use to commit ArrayBuffer , you need to construct it first Blob .
Keep an eye on the structure of the typed array
When new xxxxxArray(arrayBuffer) constructed with this overload, it is constructed by default on this basis ArrayBuffer . However, when using new xxxxArray(another_typed_array) this overload, it is "copy construction", so that the two typed array points to different buffer, it is necessary to note whether this is expected.
If you need to construct the typed array based on the same one, ArrayBuffer you can use the typed array, buffer byteLength byteOffset to get behind it ArrayBuffer .
Tips (pits) keep an eye on memory alignment
When using Arraybuffer to construct a typed array, you can specify byteOffset parameters, such as
var buffer = get_array_buffer_some_how (); var New Int16array (buffer, 10);
The above code can be constructed as a buffer starting point with a backward offset of 10 bytes, Int16Array but if you set 10 to an odd number, you will find the following error:
Rangeerror:start offset of Int16array should be a multiple of 2
This is because the typed array is required for memory pair indents, it cannot be established in a non-aligned position, and, in the same vein, the Uint32Array Int32Array offset is required to be 4-byte aligned.
So if you want to read and write in a non-aligned position, you need the help of DataView.
Keep an eye on the byte sequence.
we write in the daily program, almost do not need to care about the byte order , so this problem is not so serious, know that their program will have a byte-order problem of the people, developed here will certainly know the existence of the problem, but here is a little mention.
According to MDN, the Typed array will only use the byte order of the current platform, for example, the desktop computer we are using now, whether PC or Mac, is x86/x64, which is Little-endian.
Use DataView , not only can solve the above mentioned memory alignment problem, you can also specify the read-write byte order, the specific parameters are in the document, do not carry.
Using DataView the mate typed array can also be a technique for detecting the current platform byte order:
functionIslittleendian () {varBUF =NewArrayBuffer (2); varView =NewDataView (BUF); View.setint16 (0, 256,true);//write data explicitly with little endian //in this case, the memory layout in BUF should be varI16 =NewInt16array (BUF); //if read by little endian, it is 256; read with big endian, 1 return(I16[0] = = = 256);}
If you write a program that requires a collapsed architecture such as X86/ARM/PPC, you need to handle the byte-order carefully when exchanging files and network packets, but one way is to pre-standardize the unified byte order in these places to prevent complications. But those are off-topic.
Summary
Use ArrayBuffer to store a byte, use the typed array to construct a access window of a specific numeric type, use a DataView more precise operation on a non-aligned or caring byte order ArrayBuffer , use XHR2 Blob , File FileReader FormData ,, And many other ways to acquire or consume ArrayBuffer .
Introduction to binary operations in JS