A classe ByteArray é parte do pacote flash.utils. Para criar um objeto ByteArray no ActionScript 3.0, importe a classe ByteArray e invoque o construtor, conforme exibido no seguinte exemplo:
import flash.utils.ByteArray;
var stream:ByteArray = new ByteArray();
Métodos ByteArray
Qualquer fluxo de dados significativo é organizado em um formato que você pode analisar para encontrar as informações desejadas. Um registro em um simples arquivo de um funcionário, por exemplo, provavelmente incluiria um número de ID, um nome, um endereço, um número de telefone e assim por diante. Um arquivo de áudio MP3 contém uma marca ID3 que identifica o título, autor, álbum, data de publicação e gênero do arquivo que está sendo obtido por download. O formato permite que você saiba a ordem na qual esperar os dados no fluxo de dados. Ele permite que você leia o fluxo de bytes de modo inteligente.
A classe ByteArray inclui vários métodos que facilitam ler de e escrever para um fluxo de dados. Alguns desses métodos incluem
readBytes()
e
writeBytes()
,
readInt()
e
writeInt()
,
readFloat()
e
writeFloat()
,
readObject()
e
writeObject()
e
readUTFBytes()
e
writeUTFBytes()
. Esses métodos permitem que você leia dados do fluxo de dados em variáveis de tipos de dados específicos e escreva de tipos de dados específicos diretamente para o fluxo de dados binário.
Por exemplo, o código a seguir lê uma matriz simples de sequências de caracteres e números de ponto flutuante e escreve cada elemento em um ByteArray. A organização da matriz permite que o código chame os métodos ByteArray apropriados (
writeUTFBytes()
e
writeFloat()
) para escrever os dados. O padrão de dados repetitivo possibilita ler a matriz com um loop.
// 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
A propriedade position
A propriedade position armazena a posição atual do ponteiro que indexa ByteArray durante a leitura ou escrita. O valor inicial da propriedade position é 0 (zero), como exibido no seguinte código:
var bytes:ByteArray = new ByteArray();
trace("bytes.position is initially: " + bytes.position); // 0
Quando você lê de ou escreve em um ByteArray, o método usado atualiza a propriedade position para apontar para o local imediatamente seguindo o último byte lido ou escrito. Por exemplo, o código a seguir escreve uma sequência de caracteres em um ByteArray e, posteriormente, a propriedade position aponta para o byte imediatamente seguindo a sequência de caracteres no 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
Da mesma forma, uma operação de leitura incrementa a propriedade position pelo número de bytes lidos.
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!
Observe que você pode definir a propriedade position para um local específico no ByteArray para ler ou escrever naquele deslocamento.
As propriedades bytesAvailable e length
As propriedades
length
e
bytesAvailable
dizem a você quanto tempo um ByteArray possui e quantos bytes permanecem nele da posição atual até o fim. O exemplo a seguir ilustra como você pode usar essas propriedades. O exemplo escreve uma sequência de caracteres de texto para o ByteArray e, em seguida, lê um byte de cada vez do ByteArray até que ele encontre o caractere “a” ou o 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
}
A propriedade endian
Os computadores podem diferir em como armazenam números de vários bytes, isto é, números que exigem mais de um 1 byte de memória para armazená-los. Um inteiro, por exemplo, pode levar 4 bytes, ou 32 bits, de memória. Alguns computadores armazenam o byte mais significativo do número primeiro, no endereço de memória mais baixo e outros armazenam o byte menos significativo primeiro. Esse atributo de um computador, ou de uma ordem de bytes, é conhecido como sendo
big endian
(byte mais significativo primeiro) ou
little endian
(byte menos significativo primeiro). Por exemplo, o número 0x31323334 seria armazenado da seguinte forma para ordem de bytes big endian e little endian, onde a0 representa o endereço de memória mais baixo dos 4 bytes e a3 representa o mais alto:
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
|
A propriedade
endian
da classe ByteArray permite que você denote essa ordem de bytes para números de vários bytes que você esteja processando. Os valores aceitáveis para essa propriedade são
"bigEndian"
ou
"littleEndian"
e a classe Endian define as constantes
BIG_ENDIAN
e
LITTLE_ENDIAN
para definir a propriedade
endian
com essas sequências de caracteres.
Os métodos compress() e uncompress()
O método
compress()
permite que você compacte um ByteArray de acordo com um algoritmo de compactação especificado como um parâmetro. O método
uncompress()
permite que você descompacte um ByteArray compactado de acordo com um algoritmo de compactação. Após chamar
compress()
e
uncompress()
, o comprimento da matriz de bytes é definida para o novo comprimento e a propriedade position é definida para o fim.
A classe CompressionAlgorithm define constantes que você pode usar para especificar o algoritmo de compactação. A classe ByteArray suporta os algoritmos deflate (somente no AIR), zlib e lzma. O formato dos dados comprimidos zlib está descrito em
http://www.ietf.org/rfc/rfc1950.txt_br
. O algoritmo lzma foi adicionado ao Flash Player 11.4 e ao AIR 3.4. Ele é descrito em
http://www.7-zip.org/7z.html
.
O algoritmo de compactação deflate é usado em vários formatos de compactação, tais como zlib, gzip e algumas implementações zip. O algoritmo de compactação deflate está descrito em
http://www.ietf.org/rfc/rfc1951.txt_br
.
O exemplo a seguir compacta um ByteArray chamado
bytes
usando o algoritmo lzma:
bytes.compress(CompressionAlgorithm.LZMA);
O exemplo a seguir descompacta um ByteArray compactado usando o algoritmo deflate:
bytes.uncompress(CompressionAlgorithm.LZMA);
Leitura e escrita de objetos
Os métodos
readObject()
e
writeObject()
leem um objeto de e escrevem um objeto para um ByteArray, codificado em AMF serializado. AMF é um protocolo de mensagens proprietário criado pela Adobe e usado por várias classes do ActionScript 3.0, incluindo Netstream, NetConnection, NetStream, LocalConnection e Shared Objects.
Um marcador de tipo de um byte descreve o tipo dos dados codificados que segue. O AMF usa os 13 tipos de dados a seguir:
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
Os dados codificados seguem o marcador de tipo, a menos que o marcador represente um único valor possível, como null ou true ou false, em cujo caso nada mais é codificado.
Existem duas versões do AMF: AMF0 e AMF3. O AMF 0 suporta o envio de objetos complexos por referência e permite pontos de extremidade para restaurar as relações entre objetos. O AMF 3 melhora o AMF 0 enviando características de objetos e sequências de caracteres por referência, além de referências de objetos, e suportando novos tipos de dados introduzidos no ActionScript 3.0. A propriedade
ByteArray.objectEcoding
especifica a versão do AMF usada para codificar os dados do objeto. A classe flash.net.ObjectEncoding define constantes para especificar a versão do AMF:
ObjectEncoding.AMF0
e
ObjectEncoding.AMF3
.
O exemplo a seguir chama
writeObject()
para escrever um objeto XML para um ByteArray, que ele, em seguida compacta usando o algoritmo Deflate e escreve para o arquivo
order
na área de trabalho. O exemplo usa um rótulo para exibir a mensagem “Arquivo de ordem escrito na área de trabalho!” na janela do AIR quando concluído.
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();
}
}
O método
readObject()
lê um objeto no AMF serializado de um ByteArray e o armazena em um objeto do tipo especificado. O exemplo a seguir lê o arquivo
order
da área de trabalho em um ByteArray (
inBytes
), o descompacta e chama
readObject()
para armazená-lo no objeto XML
orderXML
. O exemplo usa uma construção de loop
for each()
para adicionar cada nó a uma área de texto para exibição. O exemplo também exibe o valor da propriedade
objectEncoding
juntamente com um cabeçalho para o conteúdo do arquivo
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();
}
}
|
|
|