Läsa och skriva en ByteArray

Flash Player 9 och senare, Adobe AIR 1.0 och senare

Klassen ByteArray tillhör paketet flash.utils. Om du vill skapa ett ByteArray-objekt i ActionScript 3.0 importerar du klassen ByteArray och anropar konstruktorn, vilket visas i exemplet nedan:

import flash.utils.ByteArray; 
var stream:ByteArray = new ByteArray();

ByteArray-metoder

Alla meningsfulla dataströmmar ordnas i ett format som du kan analysera så att du hittar den information du vill ha. I en post i en enkel anställningsfil tar du till exempel med ID-nummer, namn, adress, telefonnummer och så vidare. En MP3-ljudfil innehåller en ID3-tagg som identifierar titel, författare, album, publiceringsdatum och genre för filen som hämtas. Det här formatet gör att du vet i vilken ordning som data i strömmen förväntas. Du kan läsa byteströmmen på ett effektivt sätt.

Klassen ByteArray omfattar flera metoder som gör det enklare att läsa från och skriva till en dataström. En del av dessa metoder omfattar readBytes() och writeBytes(), readInt() och writeInt(), readFloat() och writeFloat(), readObject() och writeObject() samt readUTFBytes() och writeUTFBytes(). Med dessa metoder kan du läsa data från dataströmmen till variabler med särskilda datatyper och skriva från särskilda datatyper direkt i den binära dataströmmen.

Följande kod läser en enkel array med strängar och flyttal och skriver respektive element till en ByteArray. Strukturen på arrayen gör det möjligt för koden att anropa lämpliga ByteArray-metoder (writeUTFBytes() och writeFloat()) för att skriva data. Det återkommande datamönstret gör det möjligt att läsa arrayen med en slinga.

// 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 

Egenskapen position

Egenskapen position lagrar den aktuella positionen för pekaren som indexerar ByteArray vid läsning eller skrivning. Startvärdet för egenskapen position är 0 (noll) vilket visas i koden nedan:

var bytes:ByteArray = new ByteArray(); 
trace("bytes.position is initially: " + bytes.position);     // 0 

När du läser från eller skriver till en ByteArray uppdaterar metoder som du använder egenskapen position till att peka på platsen omedelbart efter den sista byte som lästes eller skrevs. I följande kod skrivs en sträng till en ByteArray och sedan pekar egenskapen position mot den byte som finns omedelbart efter strängen i 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 

En läsåtgärd ökar på samma sätt egenskapen position med det antal byte som läses.

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! 

Observera att du kan ange egenskapen position till en plats i en ByteArray om du vill läsa eller skriva vid den förskjutningen.

Egenskaperna bytesAvailable och length

Egenskaperna length och bytesAvailable anger hur lång en ByteArray är och hur många byte som finns kvar i den från den aktuella positionen till slutet. I följande exempel visas hur du kan använda dessa egenskaper. I exemplet skrivs en sträng med text till en ByteArray och sedan läses denna ByteArray med en byte i taget tills tecknet ”a” eller slutet (bytesAvailable <= 0) påträffas.

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 
} 

Egenskapen endian

Olika datorer kan lagra multibytetal på olika sätt, vilket innebär att tal kanske kräver mer än en byte med minne för att lagras. Ett heltal kanske till exempel behöver fyra byte, eller 32 bitar, med minne. Vissa datorer lagrar den mest signifikanta byten i siffran först, i den lägsta minnesadressen, och andra lagrar den minst signifikanta byten först. Denna byteordning kallas för big endian (mest signifikanta byte först) eller little endian (minst signifikanta byte först). Talet 0x31323334 skulle till exempel lagras på följande sätt med byteordningen big endian respektive little endian, där a0 representerar den lägsta minnesdressen på fyra byte och a3 representerar den högsta:

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

Med egenskapen endian för klassen ByteArray kan du ange denna byteordning för multibytetal som du bearbetar. Godkända värden för den här egenskapen är "bigEndian" och "littleEndian" och klassen Endian definierar konstanterna BIG_ENDIAN och LITTLE_ENDIAN när egenskapen endian ställs in med dessa strängar.

Metoderna compress() och uncompress()

Med metoden compress() kan du komprimera en ByteArray enligt en komprimeringsalgoritm som du anger som en parameter. Med metoden uncompress() kan du dekomprimera en komprimerad ByteArray enligt en komprimeringsalgoritm. När du har anropat compress() och uncompress() ställs längden på bytearrayen in på den nya längden och egenskapen position ställs in på slutet.

Klassen CompressionAlgorithm (AIR) definierar konstanter, som du kan använda för att ange komprimeringsalgoritmen. Klassen ByteArray har stöd för algoritmerna deflate (endast AIR) och zlib. Dekomprimeringsalgoritmen används i flera komprimeringsformat, till exempel zlib, gzip och en del zip-implementationer. Zlib-komprimerade dataformat beskrivs på http://www.ietf.org/rfc/rfc1950.txt och dekomprimeringsalgoritmen beskrivs på http://www.ietf.org/rfc/rfc1951.txt.

I följande exempel komprimeras en ByteArray med namnet bytes som använder dekomprimeringsalgoritmen:

bytes.compress(CompressionAlgorithm.DEFLATE);

I följande exempel dekomprimeras en komprimerad ByteArray som använder dekomprimeringsalgoritmen:

bytes.uncompress(CompressionAlgorithm.DEFLATE);

Läsa och skriva objekt

Metoderna readObject() och writeObject() kan läsa ett objekt från och skriva ett objekt till en ByteArray, kodad med AMF-serialisering (Action Message Format). AMF är ett tillverkarspecifikt meddelandeprotokoll som har skapats av Adobe och används av olika ActionScript 3.0-klasser, bland annat Netstream, NetConnection, NetStream, LocalConnection och Shared Objects.

En typmarkör på en byte beskriver vilken typ av kodade data som följer. AMF använder följande 13 datatyper:

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

Den kodade datan kommer efter typmarkören såvida inte markören representerar ett enda möjligt värde, till exempel null eller sant eller falskt. Då kodas inget annat.

Det finns två versioner av AMF: AMF0 och AMF3. AMF 0 har stöd för att skicka komplexa objekt via referens och tillåter slutpunkter att återställa objektrelationer. AMF 3 förbättrar AMF 0 genom att skicka objekt-traits och strängar via referens, förutom objektreferenserna, och genom att ha stöd för de nya datatyper som introducerades i ActionScript 3.0. Egenskapen ByteArray.objectEcoding anger vilken version av AMF som används för att koda objektdata. Klassen flash.net.ObjectEncoding definierar konstanter som anger AMF-versionen: ObjectEncoding.AMF0 och ObjectEncoding.AMF3.

Följande exempel anropar writeObject() för att skriva ett XML-objekt till en ByteArray. Sedan komprimeras objektet med hjälp av dekomprimeringsalgoritmen och skrivs till filen order på skrivbordet. I exemplet används en etikett för att visa meddelandet ”Wrote order file to desktop!” i AIR-fönstret när det är klart.

/* The following lines, minus comment characters 
, are for Flex version: 
* <?xml version="1.0" encoding="utf-8"?> 
* <mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"  
*    creationComplete="init();"> 
* <mx:Script> 
*     <![CDATA[ 
*/ 
import flash.filesystem.*; 
import flash.utils.ByteArray; 
// import mx.controls.Label for Flex 
import fl.controls.Label // for Flash; Label component must be in Library 
// for Flex: private function init():void { 
    var bytes:ByteArray = new ByteArray(); 
    var myLabel:Label = new Label(); 
    myLabel.move(150, 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 
    outFile("order", bytes); 
    myLabel.text = "Wrote order file to desktop!"; 
// for Flex: }     // end of init()function outFile(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(); 
} 
/* Add the following lines for Flex, minus comment characters: 
*     ]]> 
* </mx:Script>             
* </mx:WindowedApplication> 
*/ 

Metoden readObject() läser ett objekt i serialiserat AMF från en ByteArray och lagrar det i ett objekt av angiven typ. I följande exempel läser filen order från skrivbordet till en ByteArray (inBytes), dekomprimerar den och anropar readObject() för att lagra den i XML-objektet orderXML. I exemplet används en for each()-slingakonstruktor för att lägga till varje nod i ett textområde så att de visas. I exemplet visas också värdet på egenskapen objectEncoding tillsammans med huvudet för innehållet i filen order.

/* The following lines, minus comment characters, are for Flex version: 
* <?xml version="1.0" encoding="utf-8"?> 
* <mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" 
*     creationComplete="init();"> 
* <mx:Script> 
*         <![CDATA[ 
*/ 
import flash.filesystem.*; 
import flash.utils.ByteArray; import fl.controls.TextArea; // in Flash, TextArea component must be in Library 
// for Flex version: import mx.controls; 
// for Flex version: private function init():void {    var inBytes:ByteArray = new ByteArray(); 
    // define text area for displaying XML content 
    var myTxt:TextArea = new TextArea(); 
    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"; 
    readFile("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"; 
    }  
// for Flex version: } // end of init() // read specified file into byte array 
function readFile(fileName:String, data:ByteArray) { 
    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, 0, data.length); 
    inStream.close(); 
} 
/* Add the following lines, minus comment characters, for Flex: 
*         ]]> 
*     </mx:Script> 
*      
* </mx:WindowedApplication> 
*/