Lectura y escritura de un ByteArrayFlash Player 9 y posterior, Adobe AIR 1.0 y posterior La clase ByteArray forma parte del paquete flash.utils. Para crear un objeto ByteArray en ActionScript 3.0, importe la clase ByteArray e invoque el constructor, como se muestra en el ejemplo siguiente: import flash.utils.ByteArray; var stream:ByteArray = new ByteArray(); Métodos de ByteArrayTodo flujo de datos significativo se organiza en un formato que se pueda analizar para localizar la información deseada. Una ficha en un archivo sencillo de empleados, por ejemplo, probablemente incluiría un número de ID, nombre, dirección, teléfono, etc. Un archivo de audio MP3 contiene una etiqueta ID3 que identifica el título, autor, álbum, fecha de edición y género del archivo que se descarga. El formato permite saber el orden en que cabe esperar los datos en el flujo de datos. Permite leer el flujo de bytes con inteligencia. La clase ByteArray incluye varios métodos que facilitan la lectura y escritura en un flujo de datos, entre ellos: readBytes() y writeBytes(), readInt() y writeInt(), readFloat() y writeFloat(), readObject() y writeObject(), y readUTFBytes() y writeUTFBytes(). Estos métodos permiten leer datos desde el flujo de datos en variables de tipos de datos específicos y escribir desde tipos de datos específicos directamente en el flujo de datos binarios. En el siguiente ejemplo el código lee un conjunto sencillo de cadenas y números de punto flotante y escribe cada elemento en un ByteArray. La organización del conjunto permite que el código llame a los métodos adecuados de ByteArray (writeUTFBytes() y writeFloat()) para escribir los datos. El patrón de datos reiterado hace posible leer el conjunto con un bucle. // 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
Propiedad positionLa propiedad "position" guarda la posición actual del puntero que indexa el ByteArray durante la lectura o escritura. El valor inicial de la propiedad "position" es 0 (cero) como se muestra en el código siguiente: var bytes:ByteArray = new ByteArray();
trace("bytes.position is initially: " + bytes.position); // 0
Cuando se lee o escribe en un ByteArray, el método empleado actualiza la propiedad de posición para que apunte al lugar inmediatamente después del último byte leído o escrito. En el siguiente ejemplo, el código escribe una cadena en un ByteArray y después la propiedad de posición apunta al byte que sigue a dicha cadena en el 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
Asimismo, una operación de lectura incrementa la propiedad de posición con el número de bytes leídos. 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!
Obsérvese que se puede definir la propiedad de posición en un lugar concreto del ByteArray para leer o escribir en esa posición desplazada. Propiedades bytesAvailable y lengthLas propiedades length y bytesAvailable indican la longitud de un ByteArray y cuántos bytes quedan desde la posición actual hasta el final. El ejemplo siguiente muestra cómo utilizar estas propiedades. En el ejemplo se escribe una cadena de texto en el ByteArray y después se lee el ByteArray byte por byte hasta llegar al carácter “a” o al final (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
}
Propiedad endianLos ordenadores pueden variar en la forma en que guardan números que requieren varios bytes de memoria. Un entero, por ejemplo, puede necesitar 4 bytes (32 bits) de memoria. En alguno ordenadores se guarda primero el byte más significativo del número, en la dirección de memoria más baja, y en otros se guarda primero el byte menos significativo. Este atributo del ordenador, o de la ordenación de bytes, se denomina big endian (primero el byte más significativo) o little endian (primero el byte menos significativo). Por ejemplo: el número 0x31323334 se guardaría de la forma siguiente con ordenación de bytes big endian y little endian, en que a0 representa la dirección de memoria más baja de los 4 bytes y a3 representa la más alta:
La propiedad endian de la clase ByteArray permite indicar este orden de bytes para los números de varios bytes que se procesen. Los valores aceptables para esta propiedad son "bigEndian" o "littleEndian" y la clase Endian define las constantes BIG_ENDIAN y LITTLE_ENDIAN para definir la propiedad endian con estas cadenas. Métodos compress() y uncompress()El método compress() permite comprimir un ByteArray de acuerdo con un algoritmo de compresión especificado como parámetro. El método uncompress() permite descomprimir un ByteArray comprimido de acuerdo con un algoritmo de compresión. Tras llamar a compress() y uncompress() se define la nueva longitud del conjunto de bytes y la propiedad de posición se define en el final. La clase CompressionAlgorithm (AIR) define las constantes que se pueden utilizar para especificar el algoritmo de compresión. La clase ByteArray admite los algoritmos deflate (sólo AIR) y zlib. El algoritmo de compresión deflate se utiliza en varios formatos de compresión, como zlib, gzip y algunas implementaciones de zip. El formato de datos comprimidos zlib se describe en http://www.ietf.org/rfc/rfc1950.txt y el algoritmo de compresión deflate se describe en http://www.ietf.org/rfc/rfc1951.txt. En el siguiente ejemplo se comprime un ByteArray denominado bytes con el algoritmo deflate: bytes.compress(CompressionAlgorithm.DEFLATE); En el siguiente ejemplo se descomprime un ByteArray comprimido con el algoritmo deflate: bytes.uncompress(CompressionAlgorithm.DEFLATE); Lectura y escritura de objetosLos métodos readObject() y writeObject() leen y escriben un objeto en un ByteArray, codificado en formato de mensaje de acción (AMF) serializado. AMF es un protocolo de mensajes propio de Adobe que se utiliza en diversas clases de ActionScript 3.0, entre ellas Netstream, NetConnection, NetStream, LocalConnection y Shared Objects. Se utiliza un marcador de un byte para describir el tipo de datos codificados que siguen. AMF utiliza los siguientes 13 tipos de datos: 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
Los datos codificados siguen al marcador de tipo, a menos que el marcador represente un solo valor posible (como "null", "true" o "false"), en cuyo caso no se codifica nada más. Existen dos versiones de AMF: AMF0 y AMF3. AMF 0 es compatible con la transmisión de objetos complejos por referencia y admite puntos finales para restaurar relaciones de objetos. AMF 3 representa una mejora de AMF 0 al enviar cadenas y características de objetos mediante referencia, además de referencias de objetos, y al admitir nuevos tipos de datos que se introdujeron en ActionScript 3.0. La propiedad ByteArray.objectEcoding especifica la versión de AMF que se utiliza para codificar los datos de objeto. La clase flash.net.ObjectEncoding define las constantes para especificar la versión de AMF: ObjectEncoding.AMF0 y ObjectEncoding.AMF3. En el siguiente ejemplo se llama a writeObject() para escribir un objeto XML en un ByteArray, que a continuación se comprime con el algoritmo deflate y se escribe en el archivo order en el escritorio. En el ejemplo se utiliza una etiqueta para presentar el mensaje “Wrote order file to desktop!” en la ventana de AIR una vez terminada la operación. /* 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>
*/
El método readObject() lee un objeto de un ByteArray en AMF serializado y lo guarda en un objeto del tipo especificado. En el siguiente ejemplo se lee el archivo order del escritorio para ponerlo en un ByteArray (inBytes), se descomprime y se llama a readObject() para guardarlo en el objeto XML orderXML. En el ejemplo se utiliza una construcción de bucle for each() para añadir cada nodo a un área de texto para su visualización. En el ejemplo se muestra también el valor de la propiedad objectEncoding junto con una cabecera para el contenido del archivo 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>
*/
|
|