La classe ByteArray fait partie du package flash.utils. Afin de créer un objet ByteArray dans ActionScript 3.0, importez la classe ByteArray et appelez le constructeur, comme décrit dans l’exemple suivant :
import flash.utils.ByteArray;
var stream:ByteArray = new ByteArray();
Méthodes ByteArray
Tout flux de données significatif est organisé selon un format spécifique que vous pouvez analyser afin d’y trouver les informations souhaitées. Par exemple, un enregistrement dans un fichier d’employé simple, comprendrait très certainement un numéro d’ID, un nom, une adresse, un numéro de téléphone, etc. Un fichier audio MP3 contient une balise ID3 permettant d’identifier le titre, l’auteur, l’album, la date d’édition et le genre du fichier en cours de téléchargement. Le format vous permet de connaître l’ordre dans lequel vous devez vous attendre à recevoir les données du flux de données. Il vous permet de lire le flux d’octets de manière intelligente.
La classe ByteArray comprend plusieurs méthodes destinées à faciliter la lecture depuis un flux de données et l’écriture vers lui. Parmi les méthodes disponibles, on compte celles-ci :
readBytes()
et
writeBytes()
,
readInt()
et
writeInt()
,
readFloat()
et
writeFloat()
,
readObject()
et
writeObject()
, et
readUTFBytes()
et
writeUTFBytes()
. Grâce à ces méthodes, vous pouvez lire des données provenant du flux de données dans des variables de types de données spécifiques et écrire directement depuis ces types de données vers un flux de données binaire.
Par exemple, le code suivant lit un simple tableau de chaînes et de nombres à virgule flottante, puis écrit chaque élément vers un objet ByteArray. La structure du tableau permet au code d’appeler les méthodes ByteArray appropriées (
writeUTFBytes()
et
writeFloat()
) afin d’écrire les données. Le modèle de données répétitif permet de lire le tableau au moyen d’une boucle.
// 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
Propriété position
La propriété position stocke la position actuelle du pointeur qui indexe la classe ByteArray au cours de la lecture ou de l’écriture. La valeur initiale de la propriété position est égale à 0 (zéro) comme l’illustre l’exemple de code suivant :
var bytes:ByteArray = new ByteArray();
trace("bytes.position is initially: " + bytes.position); // 0
Lors de la lecture à partir d’une classe ByteArray ou de l’écriture vers elle, la méthode utilisée met à jour la propriété position de sorte qu’elle pointe vers l’emplacement suivant immédiatement le dernier octet lu ou écrit. Par exemple, le code suivant écrit une chaîne dans une classe ByteArray. Ensuite, la propriété position pointe vers l’octet qui suit immédiatement la chaîne dans 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
De la même manière, une opération de lecture incrémente la propriété position en fonction du nombre d’octets lus.
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!
Vous noterez qu’il est possible de définir la propriété position sur un emplacement spécifique dans la classe ByteArray afin de lire ou d’écrire selon ce décalage.
Propriétés bytesAvailable et length
Les propriétés
length
et
bytesAvailable
vous indiquent la longueur d’une classe ByteArray et le nombre d’octets restants entre la position active et la fin. L’exemple suivant illustre des modes d’utilisation de ces propriétés. L’exemple écrit une chaîne de texte dans la classe ByteArray, puis lit la classe ByteArray octet par octet jusqu’à la détection du caractère « a » ou l’arrivée au terme (
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
}
Propriété endian
Les ordinateurs ne stockent pas tous de la même manière les nombres à plusieurs octets, autrement dit, les nombres nécessitant plus d’un octet de mémoire de stockage. Un nombre entier, par exemple, peut prendre 4 octets (ou 32 bits) de mémoire. Certains ordinateurs commencent par stocker l’octet le plus important du nombre (dans l’adresse mémoire de plus bas niveau) tandis que d’autres stockent d’abord l’octet le moins important. Cet attribut d’ordinateur (ou ordre d’octets) est connu comme étant soit
gros-boutiste
(l’octet le plus important en premier lieu) soit
petit-boutiste
(l’octet le moins important en premier lieu). Par exemple, le nombre 0x31323334 serait stocké de la manière suivante pour les ordres d’octets gros-boutiste et petit-boutiste, où a0 représente l’adresse mémoire de plus bas niveau des 4 octets et a3 correspond à celle de plus haut niveau :
Gros-boutiste
|
Gros-boutiste
|
Gros-boutiste
|
Gros-boutiste
|
a0
|
a1
|
a2
|
a3
|
31
|
32
|
33
|
34
|
Petit-boutiste
|
Petit-boutiste
|
Petit-boutiste
|
Petit-boutiste
|
a0
|
a1
|
a2
|
a3
|
34
|
33
|
32
|
31
|
La propriété
endian
de la classe ByteArray vous permet de désigner cet ordre d’octets pour les nombres à plusieurs octets que vous traitez. Les valeurs admises pour cette propriété sont
bigEndian
(gros-boutiste) et
littleEndian
(petit-boutiste). La classe Endian définit les constantes
BIG_ENDIAN
et
LITTLE_ENDIAN
pour configurer la propriété
endian
à l’aide de ces chaînes.
Méthodes compress() et uncompress()
La méthode
compress()
vous permet de compresser une classe ByteArray conformément à un algorithme de compression spécifié sous forme de paramètre. La méthode
uncompress()
vous permet de décompresser un tableau ByteArray compressé conformément à un algorithme de compression. Une fois que vous avez appelé
compress()
et
uncompress()
, la longueur du tableau d’octets est fixée selon la nouvelle longueur et la propriété position est configurée sur la fin.
La classe CompressionAlgorithm définit des constantes pouvant servir à spécifier l'algorithme de compression. La classe ByteArray prend en charge les algorithmes deflate (AIR uniquement), zlib, et lzma. Le format de données compressé zlib est décrit à l’adresse
http://www.ietf.org/rfc/rfc1950.txt
. L’algorithme lzma a été ajouté à Flash Player 11.4 et AIR 3.4. Il est décrit sur la page suivante :
http://www.7-zip.org/7z.html
.
L’algorithme de compression deflate est utilisé dans plusieurs formats de compression tels que zlib, gzip et certaines implémentations zip. L’algorithme de compression deflate est décrit à l’adresse
http://www.ietf.org/rfc/rfc1951.txt
.
Dans l’exemple suivant, un tableau ByteArray appelé
bytes
est compressé à l’aide de l’algorithme Izma :
bytes.compress(CompressionAlgorithm.LZMA);
Dans l’exemple suivant, un tableau ByteArray compressé est décompressé à l’aide de l’algorithme deflate :
bytes.uncompress(CompressionAlgorithm.LZMA);
Lecture et écriture d’objets
Les méthodes
readObject()
et
writeObject()
permettent de lire un objet à partir d’une classe ByteArray et d’en écrire un dans une telle classe. Cet objet est codé au format AMF sérialisé. AMF est un protocole de message propriétaire créé par Adobe et utilisé par différentes classes ActionScript 3.0, notamment les objets Netstream, NetConnection, NetStream, LocalConnection et Shared.
Un marqueur de type « un octet » décrit le type des données codées qui suivent. Le format AMF fait appel aux 13 types de données suivants :
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
Les données codées suivent le marqueur de type à moins que ce dernier ne représente qu’une seule valeur possible (nulle, vraie ou fausse, par exemple), auquel cas aucun autre élément n’est codé.
Il existe deux versions du format AMF : AMF0 et AMF3. AMF 0 prend en charge l’envoi d’objets complexes par référence et permet aux points de fin de restaurer les relations entre objets. AMF 3 améliore le format AMF 0 en envoyant les traits et chaînes de l’objet par référence, en plus des références d’objet, et en prenant en charge de nouveaux types de données introduits dans la version 3.0 d’ActionScript. La propriété
ByteArray.objectEcoding
spécifie la version du format AMF utilisée pour coder les données d’objet. La classe flash.net.ObjectEncoding définit des constantes permettant de préciser la version du format AMF :
ObjectEncoding.AMF0
et
ObjectEncoding.AMF3
.
Dans l’exemple suivant,
writeObject()
est appelé pour écrire un objet XML dans une classe ByteArray, qu’il compresse ensuite à l’aide de l’algorithme Deflate et écrit dans le fichier
order
situé dans le poste de travail. Dans cet exemple, une étiquette affiche le message « Wrote order file to desktop! » (Fichier d’ordre écrit dans le poste de travail) dans la fenêtre d’AIR lorsque l’opération est terminée.
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();
}
}
La méthode
readObject()
lit un objet au format AMF sérialisé à partir d’une classe ByteArray et le stocke dans un objet du type spécifié. Dans l’exemple suivant, le fichier
order
est lu à partir du poste de travail dans une classe ByteArray (
inBytes
), puis il est décompressé.
readObject()
est ensuite appelé pour stocker le fichier dans l’objet XML
orderXML
. Dans cet exemple, une construction de boucle
for each()
est utilisée pour ajouter chaque nœud à une zone de texte à des fins d’affichage. L’exemple présente également la valeur de la propriété
objectEncoding
accompagnée d’un en-tête pour le contenu du fichier
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();
}
}
|
|
|