用JavaScript处理binary data

风行水上 @ 2013-11-26 16:15:46
标签:

    一直一来,JavaScritp都缺少处理二进制数据的能力。唯一算是跟二进制数据有点关系的是StringcharCodeAt()fromCharCode()方法。

    HTML5以来,JavaScript增加了新的数据类型,从而对二进制数据有了一定程度上的支持。

    ArrayBuffer和ArrayBufferView

    其中最主要的数据类型是ArrayBuffer,用来表示一串bytes。

    对二进制数据的处理则交由不同的ArrayBufferView来处理,比如:

    • Int8Array / Uint8Array
    • Int16Array / Uint16Array
    • Int32Array / Uint32Array
    • Float32Array / Float64Array

    字节序使用本机的字节序。

    var buffer = new ArrayBuffer(2);
    var bytes = Uint8Array(buffer);
    var value = bytes[1];
    

    另一个更底层的接口是DataView,提供了一组方法用于读取或修改ArrayBuffer

    • getInt8() / getUint8() / setInt8() / setUint8()
    • getInt16() / getUint16() / setInt16() / setUint16()
    • getInt32() / getUint32() / setInt32() / setUint32()
    • getFloat32() / getFloat64() / setFloat32() /setFloat64()
    var buffer = new ArrayBuffer(2);
    var view = new DataView(buffer);
    var little_endian = true;
    view.setInt16(0, 256, little_endian); // use little endian
    view.getInt16(0, little_endian );
    

    本机字节序的判断

    二进制世界不可避免地涉及到Big Endian和Little Endian的问题。

    下面的代码可以用于判断本机的字节序。

    // 引自:https://developer.mozilla.org/en-US/docs/Web/API/DataView
    
    var littleEndian = (function() {
      var buffer = new ArrayBuffer(2);
      new DataView(buffer).setInt16(0, 256, true);
      return new Int16Array(buffer)[0] === 256;
    })();
    

    二进制数据的传递

    怎样把二进制数据传送给JavaScript呢?

    一种方法是利用base64编码,通过window.atob函数转换为“字符串”,再逐字节赋值给ArrayBuffer:

    function base64tobin(base64) {
      var text = window.atob(base64);
      var buffer = new ArrayBuffer(text.length);
      var view = new DataView(buffer);
      for(var i=0, n=text.length; i<n; i++) view.setUint8(i,text.charCodeAt(i));
      return buffer;
    }
    

    window.btoa()可以把数据编码为base64。

    和字符串之间的转换

    二进制数据转为字符串,显然是和字符串的编码问题相关的。

    function bin2txt(buffer,encoding) {
      if(encoding=='ascii'){
        return String.fromCharCode.apply(null, new Uint8Array(buffer));
      }else if(encoding=='unicode' || encoding=='utf16'){
        return String.fromCharCode.apply(null, new Uint16Array(buffer)); // 使用本机字节序
      }else{
        alert('Not supported yet');
      }
    }
    
    标签:

      分享到:
      comments powered by Disqus

      18/18ms