Quick link: http://www.bobsgear.com/x/EgC4AQ {}
Problem: How to embed a text file in Flex, or how do you embed an XML file in Flex, or other text asset that you want to get as a string?
One solution, that probably worked with Flex 3, is
foobar.as
package {
import flash.utils.ByteArray;
[Embed(source="test.mxml", mimeType="application/octet-stream")]
public class foobar extends ByteArray
{
}
}
test.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="testMe()">
<mx:Script>
<![CDATA[
public var myText:foobar = new foobar();
public function testMe():void {
trace(myText.toString());
}
]]>
</mx:Script>
</mx:Application>
Source blog.flexexamples.com/2007/07/24/embedding-eternal-files-using-embed/
Unfortunately, in Flex 4 (I am using "Burrito"), you get an empty string. In the following example:
var bembed:foobar = new foobar(); BookText = bembed.toString();
BookText gets an empty string, and inspecting private members of bembed shows bytesAvailable=0
Variations of this solution are common on the web.
This page flexscript.wordpress.com/2008/08/02/embedding-text-file-into-flex/ showed a slightly different solution:
[Bindable] [Embed(source="MyFile.txt", mimeType="application/octet-stream")] private var myFileClass:Class;
Once you embedded the file like the above, the flex considers the file as ByteArrayAsset, and reference
that ByteArrayAsset to the specified variable, in our case, myFileClass variable, so we can access the
embedded file in our application, like below;
var MyFileByteArray:ByteArrayAsset = ByteArrayAsset(new myFileClass()); var story:String = MyFileByteArray.readUTFBytes(MyFileByteArray.length);
A breakpoint at the start of the constructor for the class containing the above shows that the myFileClass is initialized in some way, then control goes to the first line of the constructor.
Unfortunately, the Flex 4 debugger doesn't allow any meaningful inspection of the contents of myFileClass:
- [inherited]
- prototype Object (@b929701) - no further inspection possible
Again, story="", and MyFileByteArray.bytesAvailable=0
Another page said there was error in doing embedding in Flex 4, but I didn't encounter any compiler errors or crashes. link The solution suggested was to add a compiler switch, so I added this switch to my project, but it didn't help:
- -static-link-runtime-shared-libraries=true
To make sure my embed command was finding the right file, I tried changing STC.txt to logo.gif, and the compiler correctly gave this error:
| Description | Resource | Path | Location | Type |
|---|---|---|---|---|
| unable to resolve 'logo.gif' for transcoding | BookSTC.as | /TruthReader - Library/src/com/webmill/truthreader/books/egw/stc | line 18 | Flex Problem |
| unable to transcode 'logo.gif' |
A quick reading of Adobe's page on Using Flex 4 / Enhancing the user interface / Embedding assets / Embedding asset types might make you think this would work, but this gets a null for BookText:
[Embed(source="STC.txt",mimeType="application/octet-stream")] [Bindable] public var imgCls:Class; BookText = new imgCls() as String;
But this does not work.
Looking at the section "Embedding all other file types", leads to these ideas:
// [Embed(source="logo.bmp",mimeType="application/octet-stream")] [Embed(source="STC.txt",mimeType="application/octet-stream")] private var FileClass : Class; var fileByteArray:Object = new FileClass(); myTA.text+= "File length: " + String(fileByteArray.length) + "\n"; myTA.text+="File type: " + String(getQualifiedSuperclassName(fileByteArray)) + "\n";
This lets us know that we are dealing with a ByteArrayAsset.
This ActionScript to turn a ByteArray into a String might look correct, but it fails with a runtime error:
// Error: Error #2030: End of file was encountered. /* var bas:ByteArrayAsset = new FileClass(); BookText = bas.readUTF(); if (BookText == null) myTA.text+="#3 BookText:null"+"\n"; else myTA.text+="#3 As String length: "+BookText.length+"\n"; */
To avoid this end of file error reading from a ByteArray, we have to not read off the end of the array.
The Solution
Here is an MXML application to embed a text asset in a SWF file. I tried it as a flex file, on strings up to 171K, and everything was fine:
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:layout>
<s:VerticalLayout/>
</s:layout>
<fx:Script>
<![CDATA[
import mx.core.ByteArrayAsset;
[Embed(source="STC.txt",mimeType="application/octet-stream")]
private var FileClass : Class;
private function captureEmbeddedImage():void {
var fileByteArray:Object = new FileClass();
myTA.text+= "File length: " + String(fileByteArray.length) + "\n";
myTA.text+="File type: " +
String(getQualifiedSuperclassName(fileByteArray)) + "\n";
var bas:ByteArrayAsset = new FileClass();
var BookText:String = bas.readUTFBytes(bas.bytesAvailable);
if (BookText == null)
myTA.text+="BookText:null"+"\n";
else
myTA.text+="As String length: "+BookText.length+"\n";
}
]]>
</fx:Script>
<mx:Button
id="showProperties"
label="Show Properties"
click="captureEmbeddedImage();"/>
<mx:TextArea id="myTA"
width="75%"
height="100"/>
</s:Application>
Note that MXML apps can use getQualifiedSuperclassName directly, but in an ActionScript file it will need to be called from flash.utils package.link