Класс ByteArray входит в пакет flash.utils. Чтобы создать объект ByteArray в ActionScript 3.0, импортируйте класс ByteArray и вызовите конструктор, как показано ниже:
import flash.utils.ByteArray;
var stream:ByteArray = new ByteArray();
Методы ByteArray
Любой осмысленный поток данных организован в таком формате, который можно проанализировать, чтобы найти нужную информацию. Например, запись в личной карточке сотрудника компании скорее всего будет содержать идентификационный номер, имя, адрес, номер телефона и т. д. MP3-файл содержит тег ID3, задающий название, исполнителя, альбом, дату выпуска и жанр загружаемого файла. Формат позволяет определять порядок данных в потоке. Таким образом можно читать поток и извлекать нужные данные.
Класс ByteArray содержит несколько методов, упрощающих чтение и запись данных в поток. К ним относятся методы
readBytes()
и
writeBytes()
,
readInt()
и
writeInt()
,
readFloat()
и
writeFloat()
,
readObject()
и
writeObject()
, а также
readUTFBytes()
и
writeUTFBytes()
. Они позволяют читать данные из потока в переменные отдельных типов данных и записывать из отдельных типов данных непосредственно в двоичный поток.
Например, в коде ниже читается простой строковой массив и числа с плавающей точкой, и каждый элемент записывается в объект ByteArray. Благодаря устройству массива код способен вызвать для записи данных нужные методы ByteArray (
writeUTFBytes()
и
writeFloat()
). Повторяющаяся структура данных позволяет читать массив с помощью цикла.
// 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
Свойство position
Свойство position сохраняет текущее положение указателя, определяющего ByteArray во время чтения или записи. Исходное значение свойства position равно 0 (нулю), как показано ниже:
var bytes:ByteArray = new ByteArray();
trace("bytes.position is initially: " + bytes.position); // 0
При чтении или записи в объект ByteArray используемый метод обновляет свойство position, чтобы указать положение, следующее сразу за последним считанным или записанным байтом. Например, в коде ниже строка записывается в ByteArray, а потом свойство position указывает на байт, следующий сразу за строкой в массиве 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
Таким же образом, операция чтения увеличивает значение свойства position на количество считанных байтов.
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!
Обратите внимание, что свойство position может указывать и на конкретное положение в объекте ByteArray, из которого следует выполнять чтение или запись.
Свойства bytesAvailable и length
Свойства
length
и
bytesAvailable
сообщают длину ByteArray и количество байтов, оставшихся от текущего положения до конца. В примере ниже показано, как могут использоваться эти свойства. Строка текста записывается в объект ByteArray, а потом ByteArray читается по байтам, пока не будет обнаружен символ «а» или конец массива (
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
}
Свойство endian
Компьютеры отличаются друг от друга способами хранения многобайтовых чисел, т. е. чисел, требующих для хранения более одного байта памяти. Например, целое число может занять 4 байта или 32 бита. Одни компьютеры оставляют низший адрес памяти наиболее значимому байту, а другие — наименее значимому. Этот атрибут компьютера — или порядка данных — может называться
обратный порядок байтов
(сначала самый значимый байт) или
прямой порядок байтов
(сначала наименее значимый байт). Например, число 0x31323334 при обратном порядке байтов и прямом порядке байтов сохранялось бы следующим образом, исходя из того, что a0 — низший адрес памяти с 4 байтами, а a3 — высший:
Обратный порядок байтов
|
Обратный порядок байтов
|
Обратный порядок байтов
|
Обратный порядок байтов
|
a0
|
a1
|
a2
|
a3
|
31
|
32
|
33
|
34
|
Прямой порядок байтов
|
Прямой порядок байтов
|
Прямой порядок байтов
|
Прямой порядок байтов
|
a0
|
a1
|
a2
|
a3
|
34
|
33
|
32
|
31
|
Свойство
endian
класса ByteArray позволяет указать тот или иной порядок для многобайтовых чисел. Значением этого свойства может быть
"bigEndian"
или
"littleEndian"
, а класс Endian определяет константы
BIG_ENDIAN
и
LITTLE_ENDIAN
для задания свойства
endian
с помощью этих строк.
Методы compress() и uncompress()
Метод
compress()
позволяет сжимать объект ByteArray согласно алгоритму сжатия, заданному соответствующим параметром. Метод
uncompress()
позволяет распаковывать сжатые объекты ByteArray в соответствии с алгоритмом сжатия. После вызова методов
compress()
и
uncompress()
длина байтового массива изменяется, а свойство position принимает в качестве значения конец массива.
Класс CompressionAlgorithm определяет константы, которые могут использоваться для указания алгоритмов сжатия. Класс ByteArray поддерживает алгоритмы deflate (только для AIR), zlib и lzma. Формат упакованных данных zlib описан в документе
http://www.ietf.org/rfc/rfc1950.txt
. Алгоритм lzma был добавлен для версий Flash Player 11.4 и AIR 3.4. Его описание доступно по адресу
http://www.7-zip.org/7z.html
.
Алгоритм сжатия deflate используется несколькими форматами: zlib, gzip и некоторыми вариантами zip. Алгоритм упаковки данных deflate описан в документе
http://www.ietf.org/rfc/rfc1951.txt
.
В примере ниже объект ByteArray с именем
bytes
сжимается с помощью алгоритма lzma:
bytes.compress(CompressionAlgorithm.LZMA);
В примере ниже объект ByteArray распаковывается с помощью алгоритма deflate:
bytes.uncompress(CompressionAlgorithm.LZMA);
Чтение и запись объектов
Методы
readObject()
и
writeObject()
считывают и записывают объекты в ByteArray, кодируя их в формат AMF (Action Message Format). AMF — это запатентованный протокол передачи сообщений Adobe. Он используется различными классами языка ActionScript 3.0, включая Netstream, NetConnection, NetStream, LocalConnection и Shared Objects.
Однобайтовый маркер указывает на тип закодированных данных. В AMF используется 13 типов данных.
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
Закодированные данные следуют за маркером типа; исключением являются случаи, когда маркер представляет единственно возможное значение, например «null», «true» или «false», и тогда кодирование не осуществляется.
Существуют две версии AMF: AMF0 и AMF3. AMF 0 поддерживает отправку комплексных объектов с помощью ссылки и позволяет восстанавливать отношения объектов в конечных точках. Формат AMF 3 дополняет AMF 0: он, помимо ссылок на объекты, способен отправлять ссылки на характеристики объекта и строки, а также он поддерживает новые типы данных, представленные в ActionScript 3.0. Свойство
ByteArray.objectEcoding
указывает на версию AMF, которая использовалась для кодирования данных объекта. Класс flash.net.ObjectEncoding определяет константы для указания версии AMF:
ObjectEncoding.AMF0
и
ObjectEncoding.AMF3
.
В примере ниже метод
writeObject()
вызывается для записи XML-объекта в ByteArray, который затем сжимает его с помощью алгоритма Deflate и записывает в файл
order
на рабочем столе. В примере надпись «Wrote order file to desktop!» («Файл записан на рабочий стол!») отображается в окне AIR после окончания.
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();
}
}
Метод
readObject()
читает объект в сериализованном формате AMF из объекта ByteArray и сохраняет его в объекте заданного типа. В примере ниже файл
order
читается с рабочего стола в объект ByteArray (
inBytes
), распаковывается, а затем вызывается метод
readObject()
, сохраняющий его в XML-объекте
orderXML
. В примере используется конструкция цикла
for each()
, добавляющая каждый узел в текстовую область. В примере также отображается значение свойства
objectEncoding
и заголовок содержимого файла
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();
}
}
|
|
|