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 definierar vilka konstanter som du kan använda för att ange komprimeringsalgoritmen. Klassen ByteArray har stöd för algoritmerna deflate (endast AIR), zlib och lzma. Komprimeringsformatet zlib beskrivs på http://www.ietf.org/rfc/rfc1950.txt . lzma-algoritmen lades till i Flash Player 11.4 och AIR 3.4. Den beskrivs på http://www.7-zip.org/7z.html .

Dekomprimeringsalgoritmen används i flera komprimeringsformat, till exempel zlib, gzip och en del zip-implementationer. Deflate-komprimeringsalgoritmen beskrivs på http://www.ietf.org/rfc/rfc1951.txt .

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

bytes.compress(CompressionAlgorithm.LZMA);

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

bytes.uncompress(CompressionAlgorithm.LZMA);

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.

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(); 
    } 
}

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 .

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(); 
    } 
}