views:

276

answers:

3

I need to 'embed' a file as a string of bytes directly in AS3 code rather than calling it as an external resource.

So this works fine:

var testString = "537563636573733a20537472696e672072652d656e636f6465642e";
var testArray:ByteArray = new ByteArray();
var len:uint = testString.length;

trace("testString LENGTH: " + len.toString());

for (var i:uint = 0; i < len; i += 2) {
    var c:String = '0x' + testString.charAt(i) + testString.charAt(i + 1);

    if(i < 10) { trace("testString Byte: " + c); }

    testArray.writeByte(parseInt(c));
}

trace("testString: " + testArray.toString());
trace("testString NUMBER OF BYTES: " + testArray.length.toString());

And produces this in the console:

testString LENGTH: 54
testString Byte: 0x53
testString Byte: 0x75
testString Byte: 0x63
testString Byte: 0x63
testString Byte: 0x65
testString: Success: String re-encoded.
testString NUMBER OF BYTES: 27

So next I open my target file in a Hex editor (HxD) and copy and paste the bytes directly into my String variable, just like above and I get the following output to the console:

testString LENGTH: 97478
testString Byte: 0x50
testString Byte: 0x4B
testString Byte: 0x03
testString Byte: 0x04
testString Byte: 0x14
testString: PK```
testString NUMBER OF BYTES: 48739

...and the file (as a ByteArray) is unreadable by the same library that read it perfectly when it used it as an external resource (using URLLoader.)

I did try copying the byte string back out of my code, pasting it into the Hex editor and saving it as a file and the file was re-created correctly so I don't think it is a copy and paste issue. Also, removing the '0x' from the front of each byte string and parsing with "parseInt(c, 16)" produces exactly the same results.

For some additional background, the target file is a KMZ 3D model and the file is being parsed by Papervision3D's KMZ.as library which uses the Nochump library to unzip the KMZ file. The error message I get back when trying to pass the ByteArray to KMZ.as is:

Error: invalid zip
    at nochump.util.zip::ZipFile/findEND()
    at nochump.util.zip::ZipFile/readEND()
    at nochump.util.zip::ZipFile/readEntries()
    at nochump.util.zip::ZipFile()
    at org.papervision3d.objects.parsers::KMZ/parse()
    at org.papervision3d.objects.parsers::KMZ/load()
    at infoModel/initKMZ2()
    at infoModel()

Any thoughts and/or suggestions would be greatly appreciated.

fodder

A: 

Why not just store the data as an array of bytes instead of a string. That'll be a lot more compact (one byte per byte, instead of the multiple needed by the string), and you wouldn't have to parse back to an int.

function toByteArray(a:Array):ByteArray {
  var bytes:ByteArray = new ByteArray();
  for each(var b:int in a) {
    bytes.writeByte(b);
  }
  return bytes;
}

var testData:ByteArray = toByteArray([
  0x53, 0x75, 0x63, 0x63, 0x65, 0x73,
  0x73, 0x3a, 0x20, 0x53, 0x74, 0x72,
  0x69, 0x6e, 0x67, 0x20, 0x72, 0x65,
  0x2d, 0x65, 0x6e, 0x63, 0x6f, 0x64,
  0x65, 0x64, 0x2e //, ...
]);
Herms
Hi Herms, Thanks for the try - it's a good idea and it keeps me from having to swap between strings and bytes. Unfortunately, the same "invalid zip" error is still occurring.I also get a new error when the array containing the file's bytes is too large: "The ABC data is corrupt, attempt to read out of bounds." However, if I lower the size of my model I do not get that error.
fodder
A: 

Use the [Embed()] tag.

// Put this as a member variable in one of your classes somewhere
[Embed(source="object.kmz", mimeType="application/octet-stream")]
private static var myKMZ :Class;

Now, myKMZ will be a class that extends ByteArray.

How to get the data out:

var myKMZbytes :ByteArray = new myKMZ() as ByteArray;
davr
A: 

davr, Aaaah, I didn't realize that Flash CS4 supported the Embed tag (CS3 did not and because of my development situation I can not use Flex.) Thanks a million.

I would mark yours as the answer but I posted as unregistered and can no longer reply as the question's author.

Actually, even though your answer works for my problem, I am still curious why the ByteArray wouldn't work. I could see that method being very helpful in some instances.

Anyway, thanks again, fodder

fodder