I was wondering if there was any way to import a binary file format and read its data into a script. A text file would be easier as you can use TextAsset.text, but what if the file is not text?
The only other way of reading a file is TextAsset.bytes, but I can’t find a way to interpret those bytes into any value type (except a String). If this works it could allow us to import a point cache file and use it to animate a mesh.
I can create a string from the Byte array using this:
//fileHeader is a byte[]
string s = System.Text.ASCIIEncoding.ASCII.GetString(fileHeader)
However, I have not found a way of turning 4 consecutive bytes (32 bits) into an int. Has anyone done this? If it can’t be done then what is the purpose of a byte array and TextAsset.bytes?
Everything is made from bytes, so they can represent whatever you want. One way is to use System.BitConverter, though it’s not endian-aware so you need to account for big-endian and little-endian systems yourself.
–Eric
This is right off the top of my head so it might not be perfect, but I imagine you’d do something similar to:
function FourBytesToInt( byte : Whatever[] ) : int {
return parseInt(byte[3]) + parseInt(byte[2] * 256) + parseInt(byte[1]*256*256) + parseInt(byte[0]*256*256*256);
}
Could be 0,1,2,3 if your endian-ness is the other one.
Edit: Oh hai, Eric, didn’t see you there. Xd
Thanks for those comments. I didn’t realise we could use BitConverter, but it works perfectly. I didn’t have to use the manual method, but that will be a good idea if no other class can do it for me.
BitConverter works, but is it ever slow! I’m trying to convert a byte array into a series of Vector3’s, so I’m doing things like this:
for (var i : int = 0; i < verts.length; +i)
{
verts[i].x = BitConvert.ToSingle(bytes, i*12);
verts[i].y = BitConvert.ToSingle(bytes, i*12+4);
verts[i].z = BitConvert.ToSingle(bytes, i*12+8);
}
For a 16,625 element array it takes nearly a minute! That means each call to BitConvert.ToSingle() is taking over a millisecond, which seem ridiculous considering what it must be doing (which is not very much).
Anyone encountered this before? Am I missing something? And are there faster alternatives?
In C, I would of course just do
verts[i].x = *((float *) &bytes[i*12]);
but I don’t think I can do that kind of casting in Unityscript or C#.
Found a solution:
var s = new MemoryStream(www.bytes);
var b = new BinaryReader(s);
var verts = new Vector3[smr.sharedMesh.vertices.length]; // new vertex array
for (var i : int = 0; i < verts.length; ++i)
{
verts[i].x = b.ReadSingle();
verts[i].y = b.ReadSingle();
verts[i].z = b.ReadSingle();
}
b.Close();
s.Close();
… much, much faster. Still no idea why mono’s BitConverter is so slow.
What is “BitConvert.ToSingle”? Using System.BitConverter.ToSingle, I can do over 25000 calls in 1 ms on my computer.
–Eric