jDataView provides a standard way to read binary files in all the browsers. It follows the DataView Specification and even extends it for a more practical use.

Explanation

There are three ways to read a binary file from the browser.

  • The first one is to download the file through XHR with charset=x-user-defined. You get the file as a String, and you have to rewrite all the decoding functions (getUint16, getFloat32, ...). All the browsers support this.
  • Then browsers that implemented WebGL also added ArrayBuffers. It is a plain buffer that can be read with views called TypedArrays (Int32Array, Float64Array, ...). You can use them to decode the file but this is not very handy. It has big drawback, it can't read non-aligned data. It is supported by Firefox 4 and Chrome 7.
  • A new revision of the specification added DataViews. It is a view around your buffer that can read arbitrary data types directly through functions: getUint32, getFloat64 ... Only Chrome 9 supports it.

jDataView provides the DataView API for all the browsers using the best available option between Strings, TypedArrays and DataViews.

API

See the specification for a detailed API. http://www.khronos.org/registry/webgl/doc/spec/TypedArray-spec.html#6. Any code written for DataView will work with jDataView (except if it writes something).

Constructor

  • new jDataView(buffer, offset, length). buffer can be either a String or an ArrayBuffer

Specification API

The wrapper satisfies all the specification getters.

  • getInt8(byteOffset)
  • getUint8(byteOffset)
  • getInt16(byteOffset, littleEndian)
  • getUint16(byteOffset, littleEndian)
  • getInt32(byteOffset, littleEndian)
  • getUint32(byteOffset, littleEndian)
  • getFloat32(byteOffset, littleEndian)
  • getFloat64(byteOffset, littleEndian)

Extended Specification

The byteOffset parameter is now optional. If you omit it, it will read right after the latest read offset. You can interact with the internal pointer with those two functions.

  • seek(byteOffset): Moves the internal pointer to the position
  • tell(): Returns the current position

Addition of getChar and getString utilities.

  • getChar(byteOffset)
  • getString(length, byteOffset)

Addition of createBuffer, a utility to easily create buffers with the latest available storage type (String or ArrayBuffer).

  • createBuffer(byte1, byte2, ...)

Shortcomings

  • Only the Read API is being wrapped, jDataView does not provide any set method.
  • The Float64 implementation on strings does not have full precision.

Example

First we need a file. Either you get it through XHR or use the createBuffer utility.

var file = jDataView.createBuffer(
	0x10, 0x01, 0x00, 0x00, // Int32 - 272
	0x90, 0xcf, 0x1b, 0x47, // Float32 - 39887.5625
	0, 0, 0, 0, 0, 0, 0, 0, // 8 blank bytes
	0x4d, 0x44, 0x32, 0x30, // String - MD20
	0x61                    // Char - a
);

Now we use the DataView as defined in the specification, the only thing that changes is the c before jDataView.

var view = new jDataView(file);
var version = view.getInt32(0); // 272
var float = view.getFloat32(4); // 39887.5625

The wrapper extends the specification to make the DataView easier to use.

var view = new jDataView(file);
// A position counter is managed. Remove the argument to read right after the last read.
version = view.getInt32(); // 272
float = view.getFloat32(); // 39887.5625
 
// You can move around with tell() and seek()
view.seek(view.tell() + 8);
 
// Two helpers: getChar and getString will make your life easier
var tag = view.getString(4); // MD20
var char = view.getChar(); // a

Demos

I'm working on a World of Warcraft Model Viewer. It uses jDataView to read the binary file and then WebGL to display it. Stay tuned for more infos about it 🙂

If you liked this article, you might be interested in my Twitter feed as well.
 
 

Related Posts

  • August 20, 2011 Idea – mouseFreeze – A solution for Browser FPS Games (8)
    There is an open problem in porting real game into the web browser related to cursor handling. Problem Many games such as First-Person Shooters require the mouse to freely move, without the constraints of screen edges. However there is no such API in the browser to make this […]
  • January 26, 2011 Javascript – jQuery Binary Ajax (14)
    I made a DataView API Wrapper to read binary data from either a string or a binary buffer. You probably want to load it from a file, so you need to make a XHR request. Sadly no ajax wrapper implement it yet. XHR and Binary In order to get a binary string one must use the […]
  • September 11, 2011 WebGL – Julia 3D Representation (0)
    At school we've been studying Lie Algebra and we were asked to make a 3D representation of a Lie Group. We chose to represent Julia Set in the Quaternion domain. We were really impressed to see that it was possible to generate many different forms given such a simple […]
  • September 17, 2011 WoW Interface Anchor Positioning (5)
    I've always found CSS positioning with both float and position: absolute/relative hard to work with. I want to introduce to you an alternative way borrowed from the World of Warcraft Interface: Anchors. Anchor The concept is extremely simple. You can tell where you want the element […]
  • August 29, 2011 Javascript: Improve Cache Performance: Reduce Lookups (2)
    In my Binary Decision Diagram Library, the performance bottleneck was the uniqueness cache. By reducing the number of cache lookup, it is possible to greatly improve the performances. Common pattern In order to test if the key is already in the cache, the usual pattern is to use key […]