Lettura e scrittura di un ByteArrayFlash Player 9 e versioni successive, Adobe AIR 1.0 e versioni successive La classe ByteArray fa parte del pacchetto flash.utils. Per creare un oggetto ByteArray in ActionScript 3.0, importate la classe ByteArray e chiamate il constructor, come illustrato nel seguente esempio: import flash.utils.ByteArray; var stream:ByteArray = new ByteArray(); Metodi ByteArrayUn flusso di dati significativo è organizzato in un formato che è possibile analizzare per trovare le informazioni desiderate. Un record in un file di dipendenti semplice, ad esempio, include probabilmente un numero di identificazione, un nome, un indirizzo, un numero di telefono e così via, mentre un file audio MP3 contiene un tag ID3 che identifica il titolo, l'autore, l'album, la data di pubblicazione e il genere del file che si sta scaricando. Il formato consente di conoscere l'ordine in cui prevedere i dati nel flusso di dati e di leggere tale flusso in modo intelligente. La classe ByteArray include diversi metodi che semplificano la lettura e la scrittura in un flusso di dati. Alcuni di questi metodi includono readBytes() e writeBytes(), readInt() e writeInt(), readFloat() e writeFloat(), readObject() e writeObject(), and readUTFBytes() e writeUTFBytes(). Tali metodi consentono di leggere i dati dal flusso di dati in variabili di tipi di dati specifici, nonché di scrivere da tipi di dati specifici direttamente nel flusso di dati binario. Ad esempio, il codice riportato di seguito legge un semplice array di stringhe e di numeri a virgola mobile e scrive ciascun elemento in un ByteArray. L'organizzazione dell'array consente al codice di chiamare i metodi ByteArray appropriati (writeUTFBytes() e writeFloat()) per la scrittura dei dati. Il modello di dati ripetitivo rende possibile la lettura ciclica dell'array. // 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
La proprietà positionLa proprietà position consente di archiviare la posizione corrente del puntatore che indicizza il ByteArray durante lettura o scrittura. Il valore iniziale della proprietà position property è 0 (zero), come illustrato nel codice seguente: var bytes:ByteArray = new ByteArray();
trace("bytes.position is initially: " + bytes.position); // 0
Quando si legge o si scrive in un ByteArray, il metodo utilizzato aggiorna la proprietà position in modo che punti al percorso immediatamente successivo all'ultimo byte letto o scritto. Ad esempio, il codice seguente scrive una stringa in un ByteArray e successivamente la proprietà position punta al byte che segue immediatamente la stringa in 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
Analogamente, un'operazione di lettura incrementa la proprietà position in base al numero di byte letti. 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!
Si noti che è possibile impostare la proprietà position su una posizione specifica di ByteArray in modo che la lettura o la scrittura venga effettuata a quell'offset. Le proprietà bytesAvailable e lengthLe proprietà length e bytesAvailable indicano quanto è lungo un ByteArray e quanti byte restano dalla posizione corrente fino alla fine. Nell'esempio seguente viene illustrato come è possibile utilizzare queste proprietà. Nell'esempio viene scritta una Stringa di testo nel ByteArray e quindi il ByteArray viene letto un byte alla volta fino a che incontra il carattere “a” oppure la fine (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
}
La proprietà endianI computer possono presentare differenze nel modo in cui memorizzano numeri multibyte, vale a dire numeri che richiedono più di 1 byte di memoria per la memorizzazione. Un numero intero, ad esempio, può richiedere 4 byte o 32 bit di memoria. Alcuni computer memorizzano innanzitutto il byte più significativo del numero nell'indirizzo di memoria più basso, mentre altri memorizzano prima quello meno significativo. Questo attributo di un computer, o dell'ordinamento di byte, viene definito come big endian (prima il byte più significativo) o little endian (prima il byte meno significativo). Ad esempio, il numero 0x31323334 verrebbe archiviato come segue per l'ordinamento di byte big endian e little endian, laddove a0 indica l'indirizzo di memoria più basso dei 4 byte e a3 rappresenta quello più alto:
La proprietà endian della classe ByteArray consente di denotare l'ordine dei byte per i numeri multibyte che si sta elaborando. I valori accettabili per questa proprietà sono "bigEndian" o "littleEndian", e la classe Endian definisce le costanti BIG_ENDIAN e LITTLE_ENDIAN per impostare la proprietà endian con tali stringhe. I metodi compress() e uncompress()Il metodo compress() consente di comprimere un ByteArray in conformità a un algoritmo di compressione specificato come parametro dall'utente. Il metodo uncompress() consente di decomprimere un ByteArray compresso in conformità a un algoritmo di compressione. Dopo aver chiamato i metodi compress() e uncompress(), la lunghezza dell'array di byte è impostata sulla nuova lunghezza, mentre la proprietà position è impostata sulla fine. La classe CompressionAlgorithm (AIR) definisce le costanti che potete utilizzare per specificare l'algoritmo di compressione. La classe ByteArray supporta gli algoritmi deflate (solo AIR) e zlib. L'algoritmo di compressione deflate è utilizzato in diversi formati di compressione, ad esempio zlib, gzip e alcune implementazioni zip. Il formato di dati compresso zlib è descritto in http://www.ietf.org/rfc/rfc1950.txt mentre l'algoritmo di compressione deflate è descritto in http://www.ietf.org/rfc/rfc1951.txt. Nell'esempio seguente viene compresso un ByteArray denominato bytes mediante l'algoritmo deflate: bytes.compress(CompressionAlgorithm.DEFLATE); Nell'esempio seguente un ByteArray compresso viene decompresso mediante l'algoritmo deflate: bytes.uncompress(CompressionAlgorithm.DEFLATE); Lettura e scrittura di oggettiI metodi readObject() e writeObject() leggono un oggetto e scrivono un oggetto in un ByteArray, codificato in linguaggio AMF (Action Message Format) serializzato. AMF è un protocollo di messaggistica proprietario creato da Adobe e utilizzato da varie classi ActionScript 3.0, incluse Netstream, NetConnection, NetStream, LocalConnection e Shared Objects. Un indicatore di tipo a un solo byte descrive il tipo di dati codificati che seguono. AMF utilizza i seguenti 13 tipi di dati: 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
I dati codificati seguono l'indicatore di tipi a meno che tale indicatore non rappresenti un singolo valore possibile, ad esempio null, true o false, nel qual caso null'altro viene codificato. Sono presenti due versioni di AMF: AMF0 e AMF3. AMF 0 supporta l'invio di oggetti complessi in base a riferimento e consente agli endpoint di ripristinare le relazioni tra gli oggetti. AMF 3 migliora AMF 0 mediante l'invio di oggetti trait e stringhe in base a riferimento, oltre ai riferimenti agli oggetti, e mediante il supporto di nuovi tipi di dati introdotti in ActionScript 3.0. La proprietà ByteArray.objectEcoding consente di specificare la versione di AMF utilizzata per la codifica dei dati oggetto. La classe flash.net.ObjectEncoding definisce le costanti per la specifica della versione AMF: ObjectEncoding.AMF0 e ObjectEncoding.AMF3. Nell'esempio seguente viene chiamato writeObject() per la scrittura di un oggetto XML in un ByteArray, che viene quindi compresso mediante l'algoritmo Deflate e scritto nel file order sul desktop. Nell'esempio viene utilizzata un'etichetta per visualizzare il messaggio “Wrote order file to desktop!” (File di ordinamento scritto sul desktop), al termine nella finestra AIR. /* 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>
*/
Il metodo readObject() regge un oggetto in formato AMF serializzato da un ByteArray e lo archivia in un oggetto del tipo specificato. Nell'esempio seguente il file order sul desktop viene letto in un ByteArray (inBytes) e decompresso. Viene quindi effettuata la chiamata a readObject() per archiviarlo nell'oggetto XML orderXML. Nell'esempio viene utilizzato un costrutto di ciclo for each() per aggiungere ciascun nodo a un'area di testo per la visualizzazione. Inoltre, viene visualizzato il valore della proprietà objectEncoding insieme a un'intestazione per il contenuto del file 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>
*/
|
|