Die ByteArray-Klasse ist Teil des Pakets flash.utils. Erstellen Sie ein ByteArray-Objekt in ActionScript 3.0, indem Sie wie im folgenden Beispiel dargestellt die ByteArray-Klasse importieren und den Konstruktur aufrufen:
import flash.utils.ByteArray;
var stream:ByteArray = new ByteArray();
ByteArray-Methoden
Jeder aussagekräftige Datenstrom ist in einem Format angeordnet, das Sie analysieren können, um die gewünschten Informationen zu finden. Ein Datensatz in einer einfachen Arbeitnehmerdatei enthält zum Beispiel in der Regel eine Kennnummer, einen Namen, eine Adresse, eine Telefonnummer und weitere Daten. Eine MP3-Audiodatei enthält einen ID3-Tag, der Titel, Autor, Album, Veröffentlichungsdatum und Genre der herunterzuladenden Datei angibt. Anhand des Formats wissen Sie, in welcher Reihenfolge Sie die Daten im Datenstrom zu erwarten haben. So können Sie den Bytestrom intelligent lesen.
Die ByteArray-Klasse umfasst mehrere Methoden, die das Lesen von und Schreiben in einem Datenstrom erleichtern. Zu diesen Methoden gehören
readBytes()
und
writeBytes()
,
readInt()
und
writeInt()
,
readFloat()
und
writeFloat()
,
readObject()
und
writeObject()
und
readUTFBytes()
und
writeUTFBytes()
. Mit diesen Methoden können Sie Daten vom Datenstrom in Variablen bestimmter Datentypen lesen und von bestimmten Datentypen direkt in den binären Datenstrom schreiben.
Der folgende Code liest zum Beispiel ein einfaches Array von Strings und Gleitkommazahlen und schreibt jedes Element in ein ByteArray. Der Aufbau des Arrays erlaubt es dem Code, die entsprechende ByteArray-Methode aufzurufen (
writeUTFBytes()
und
writeFloat()
), um die Daten zu schreiben. Aufgrund des sich wiederholenden Datenmusters kann das Array mit einer Schleife gelesen werden.
// The following example reads a simple Array (groceries), made up of strings
// and floating-point numbers, and writes it to a ByteArray.
import flash.utils.ByteArray;
// define the grocery list Array
var groceries:Array = ["milk", 4.50, "soup", 1.79, "eggs", 3.19, "bread" , 2.35]
// define the ByteArray
var bytes:ByteArray = new ByteArray();
// for each item in the array
for (var i:int = 0; i < groceries.length; i++) {
bytes.writeUTFBytes(groceries[i++]); //write the string and position to the next item
bytes.writeFloat(groceries[i]); // write the float
trace("bytes.position is: " + bytes.position); //display the position in ByteArray
}
trace("bytes length is: " + bytes.length); // display the length
Die Eigenschaft „position“
Mit der Eigenschaft „position“ wird die aktuelle Position des Zeigers gespeichert, der das ByteArray während des Lese- oder Schreibvorgangs indiziert. Der Anfangswert der Eigenschaft ist wie im folgenden Code dargestellt 0 (Null):
var bytes:ByteArray = new ByteArray();
trace("bytes.position is initially: " + bytes.position); // 0
Wenn Sie von einem ByteArray lesen oder in es schreiben, aktualisiert die verwendete Methode die Eigenschaft „position“ so, dass sie auf die Stelle direkt hinter dem letzten Byte verweist, das gelesen oder geschrieben wurde. Der folgende Code schreibt zum Beispiel einen String in ein ByteArray und die Eigenschaft „position“ verweist danach auf das Byte direkt nach dem String im ByteArray:
var bytes:ByteArray = new ByteArray();
trace("bytes.position is initially: " + bytes.position); // 0
bytes.writeUTFBytes("Hello World!");
trace("bytes.position is now: " + bytes.position); // 12
Bei einem Lesevorgang wird die Eigenschaft „position“ ebenfalls um die Anzahl der gelesenen Byte erhöht.
var bytes:ByteArray = new ByteArray();
trace("bytes.position is initially: " + bytes.position); // 0
bytes.writeUTFBytes("Hello World!");
trace("bytes.position is now: " + bytes.position); // 12
bytes.position = 0;
trace("The first 6 bytes are: " + (bytes.readUTFBytes(6))); //Hello
trace("And the next 6 bytes are: " + (bytes.readUTFBytes(6))); // World!
Beachten Sie, dass Sie die Eigenschaft „position“ auf eine bestimmte Stelle im ByteArray setzen können, um ab dieser Stelle zu lesen oder zu schreiben.
Die Eigenschaften „bytesAvailable“ und „length“
Die Eigenschaften
length
und
bytesAvailable
geben an, wie lang ein ByteArray ist und wie viele Byte ab der aktuellen Position bis zum Ende verbleiben. Im folgenden Beispiel wird gezeigt, wie Sie diese Eigenschaften einsetzen können. Im Beispiel wird ein Textstring in das ByteArray geschrieben und das ByteArray dann Byte für Byte gelesen, bis der Buchstabe „a“ oder das Ende erreicht wird (
bytesAvailable <= 0
).
var bytes:ByteArray = new ByteArray();
var text:String = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Vivamus etc.";
bytes.writeUTFBytes(text); // write the text to the ByteArray
trace("The length of the ByteArray is: " + bytes.length); // 70
bytes.position = 0; // reset position
while (bytes.bytesAvailable > 0 && (bytes.readUTFBytes(1) != 'a')) {
//read to letter a or end of bytes
}
if (bytes.position < bytes.bytesAvailable) {
trace("Found the letter a; position is: " + bytes.position); // 23
trace("and the number of bytes available is: " + bytes.bytesAvailable); // 47
}
Die Eigenschaft „endian“
Verschiedene Computer verwenden verschiedene Verfahren für das Speichern aus mehreren Byte bestehender Zahlen, also Zahlen, die mehr als ein Byte Speicherplatz benötigen. Eine Ganzzahl kann beispielsweise 4 Byte, oder 32 Bit, Speicherplatz beanspruchen. Einige Computer speichern das höchstwertigste Byte der Zahl zuerst, an der niedrigsten Speicheraddresse, andere Computer speichern das niedrigwertigste Byte zuerst. Dieses Attribut der Computer, die Byte-Reihenfolge, wird als
big endian
(höchstwertigstes Byte zuerst) oder
little endian
(niedrigwertigstes Byte zuerst) bezeichnet. Die Zahl 0x31323334 wird nach den Systemen big endian und little endian wie folgt gespeichert, wobei a0 für die niedrigste Speicheradresse der 4 Byte steht und a3 für die höchste:
Big Endian
|
Big Endian
|
Big Endian
|
Big Endian
|
a0
|
a1
|
a2
|
a3
|
31
|
32
|
33
|
34
|
Little Endian
|
Little Endian
|
Little Endian
|
Little Endian
|
a0
|
a1
|
a2
|
a3
|
34
|
33
|
32
|
31
|
Mit der Eigenschaft
endian
der ByteArray-Klasse können Sie diese Byte-Reihenfolge für aus mehreren Byte bestehende Zahlen, die Sie verarbeiten, angeben. Die anerkannten Werte für diese Eigenschaft lauten entweder
„bigEndian"
oder
„littleEndian"
und die Endian-Klasse definiert die Konstanten
BIG_ENDIAN
und
LITTLE_ENDIAN
für die Einstellung der Eigenschaft
endian
mit diesen Strings.
Die Methoden „compress()“ und „uncompress()“
Mit der Methode
compress()
können Sie ein ByteArray entsprechend eines als Parameter angegebenen Komprimierungsalgorithmus komprimieren. Mit der Methode
uncompress()
dagegen können Sie ein komprimiertes ByteArray entsprechend eines als Parameter angegebenen Komprimierungsalgorithmus dekomprimieren. Nach Aufruf von
compress()
und
uncompress()
werden die Länge des Byte-Arrays auf die neue Länge und die Eigenschaft „position“ auf das Ende gesetzt.
Die CompressionAlgorithm-Klasse definiert Konstanten, mit denen Sie den Komprimierungsalgorithmus angeben können. Die ByteArray-Klasse unterstützt die Algorithmen deflate (nur AIR), zlib und lzma. Eine Beschreibung des komprimierten Datenformats zlib finden Sie unter
http://www.ietf.org/rfc/rfc1950.txt
. Der lzma-Algorithmus wurde für Flash Player 11.4 und AIR 3.4 hinzugefügt. Eine Beschreibung finden Sie unter
http://www.7-zip.org/7z.html
.
Der Komprimierungsalgorithmus „deflate“ wird in verschiedenen Komprimierungsformaten wie zlib, gzip und einigen zip-Implementationen verwendet. Eine Beschreibung des Komprimierungsalgorithmus deflate finden Sie unter
http://www.ietf.org/rfc/rfc1951.txt
.
Im folgenden Beispiel wird ein ByteArray mit dem Namen
bytes
mithilfe des lzma-Algorithmus komprimiert:
bytes.compress(CompressionAlgorithm.LZMA);
Im folgenden Beispiel wird ein komprimiertes ByteArray mit dem Algorithmus „deflate“ dekomprimiert:
bytes.uncompress(CompressionAlgorithm.LZMA);
Lesen und Schreiben von Objekten
Die Methoden
readObject()
und
writeObject()
lesen ein Objekt aus und schreiben es im serialisierten Action Message Format (AMF) in ein ByteArray. AMF ist ein herstellerspezifisches Meldungsprotokoll von Adobe, das in verschiedenen ActionScript 3.0-Klassen, einschließlich Netstream, NetConnection, NetStream, LocalConnection und Shared Objects, eingesetzt wird.
Eine aus einem Byte bestehende Markierung gibt den Typ der kodierten Daten an, die folgen. AMF verwendet die folgenden 13 Datentypen:
value-type = undefined-marker | null-marker | false-marker | true-marker | integer-type |
double-type | string-type | xml-doc-type | date-type | array-type | object-type |
xml-type | byte-array-type
Die kodierten Daten folgen der Typmarkierung, es sei denn, die Markierung steht für einen einzigen möglichen Wert, wie null, true oder false. In diesem Fall sind sonst keine Daten kodiert.
Es stehen zwei AMF-Versionen zur Verfügung: AMF 0 und AMF 3. AMF 0 unterstützt die Sendung komplexer Objekte durch Referenzen und lässt die Wiederherstellung von Objektbeziehungen durch Endpunkte zu. AMF 3 stellt gegenüber AMF 0 eine Verbesserung dar, da zusätzlich zu den Objektverweisen Objektmerkmale und Strings durch Referenzen gesendet werden können und in ActionScript 3.0 eingeführte neue Datentypen unterstützt werden. Die Eigenschaft
ByteArray.objectEcoding
gibt die AMF-Version an, die zur Kodierung der Objektdaten verwendet wird. Die Klasse flash.net.ObjectEncoding legt die Konstanten für die Angabe der AMF-Version fest:
ObjectEncoding.AMF0
und
ObjectEncoding.AMF3
.
Im folgenden Beispiel wird
writeObject()
aufgerufen, um ein XML-Objekt in ein ByteArray zu schreiben. Dieses wird dann mit dem deflate-Algorithmus komprimiert und in die Datei
order
auf dem Desktop geschrieben. Nach Abschluss des Vorgangs wird im AIR-Fenster die Meldung „Wrote order file to desktop!“ eingeblendet.
import flash.filesystem.*;
import flash.display.Sprite;
import flash.display.TextField;
import flash.utils.ByteArray;
public class WriteObjectExample extends Sprite
{
public function WriteObjectExample()
{
var bytes:ByteArray = new ByteArray();
var myLabel:TextField = new TextField();
myLabel.x = 150;
myLabel.y = 150;
myLabel.width = 200;
addChild(myLabel);
var myXML:XML =
<order>
<item id='1'>
<menuName>burger</menuName>
<price>3.95</price>
</item>
<item id='2'>
<menuName>fries</menuName>
<price>1.45</price>
</item>
</order>;
// Write XML object to ByteArray
bytes.writeObject(myXML);
bytes.position = 0; //reset position to beginning
bytes.compress(CompressionAlgorithm.DEFLATE); // compress ByteArray
writeBytesToFile("order.xml", bytes);
myLabel.text = "Wrote order file to desktop!";
}
private function writeBytesToFile(fileName:String, data:ByteArray):void
{
var outFile:File = File.desktopDirectory; // dest folder is desktop
outFile = outFile.resolvePath(fileName); // name of file to write
var outStream:FileStream = new FileStream();
// open output file stream in WRITE mode
outStream.open(outFile, FileMode.WRITE);
// write out the file
outStream.writeBytes(data, 0, data.length);
// close it
outStream.close();
}
}
Die Methode
readObject()
liest ein Objekt im serialisierten AMF aus dem ByteArray und speichert es in einem Objekt des angegebenen Typs. Im folgenden Beispiel wird die Datei
order
aus dem Desktop in ein ByteArray (
inBytes
) gelesen, dekomprimiert und es wird
readObject()
aufgerufen, um die Daten im XML-Objekt
orderXML
zu speichern. Es wird das Schleifenkonstrukt
for each()
verwendet, um jeden Knoten für die Anzeige zu einem Textbereich hinzuzufügen. Das Beispiel zeigt auch den Wert der Eigenschaft
objectEncoding
sowie einen Header für die Inhalte der Datei
order
an.
import flash.filesystem.*;
import flash.display.Sprite;
import flash.display.TextField;
import flash.utils.ByteArray;
public class ReadObjectExample extends Sprite
{
public function ReadObjectExample()
{
var inBytes:ByteArray = new ByteArray();
// define text area for displaying XML content
var myTxt:TextField = new TextField();
myTxt.width = 550;
myTxt.height = 400;
addChild(myTxt);
//display objectEncoding and file heading
myTxt.text = "Object encoding is: " + inBytes.objectEncoding + "\n\n" + "order file: \n\n";
readFileIntoByteArray("order", inBytes);
inBytes.position = 0; // reset position to beginning
inBytes.uncompress(CompressionAlgorithm.DEFLATE);
inBytes.position = 0; //reset position to beginning
// read XML Object
var orderXML:XML = inBytes.readObject();
// for each node in orderXML
for each (var child:XML in orderXML)
{
// append child node to text area
myTxt.text += child + "\n";
}
}
// read specified file into byte array
private function readFileIntoByteArray(fileName:String, data:ByteArray):void
{
var inFile:File = File.desktopDirectory; // source folder is desktop
inFile = inFile.resolvePath(fileName); // name of file to read
var inStream:FileStream = new FileStream();
inStream.open(inFile, FileMode.READ);
inStream.readBytes(data);
inStream.close();
}
}
|
|
|