ByteArray 읽기 및 쓰기

Flash Player 9 이상, Adobe AIR 1.0 이상

ByteArray 클래스는 flash.utils 패키지의 일부입니다. ActionScript 3.0에서 ByteArray 객체를 만들려면 다음 예제와 같이 ByteArray 클래스를 가져오고 생성자를 호출합니다.

import flash.utils.ByteArray; 
var stream:ByteArray = new ByteArray();

ByteArray 메서드

의미 있는 모든 데이터 스트림은 원하는 정보를 분석하여 찾을 수 있는 형식으로 구성됩니다. 예를 들어 간단한 직원 파일의 레코드에는 ID 번호, 이름, 주소, 전화 번호 등이 포함됩니다. 또한 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에 텍스트 문자열을 쓴 다음 문자 "a"가 발생하거나 끝( bytesAvailable <= 0 )에 도달할 때까지 한 번에 한 바이트씩 ByteArray를 읽습니다.

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 속성

저장하는 데 1바이트가 넘는 메모리가 필요한 멀티바이트 숫자를 저장하는 방법은 컴퓨터에 따라 다를 수 있습니다. 예를 들어 정수는 4바이트 또는 32비트의 메모리를 사용할 수 있습니다. 일부 컴퓨터는 숫자의 최상위 바이트를 가장 낮은 메모리 주소에 먼저 저장하고 다른 컴퓨터는 최하위 바이트를 먼저 저장합니다. 컴퓨터 또는 바이트 순서 지정의 이러한 특성을 big endian (최상위 바이트 우선) 또는 little endian (최하위 바이트 우선)이라고 합니다. 예를 들어 숫자 0x31323334는 big endian 및 little endian 바이트 순서 지정에 대해 다음과 같이 저장됩니다. 여기서 a0은 4바이트의 가장 낮은 메모리 주소를 나타내고 a3은 가장 높은 메모리 주소를 나타냅니다.

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

ByteArray 클래스의 endian 속성을 사용하면 처리하는 멀티바이트 숫자에 대해 이러한 바이트 순서를 나타낼 수 있습니다. 이 속성에 사용할 수 있는 값은 "bigEndian" 또는 "littleEndian" 입니다. Endian 클래스는 이러한 문자열을 사용하여 endian 속성을 설정하기 위한 BIG_ENDIAN LITTLE_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 를 참조하십시오.

다음 예제에서는 lzma 알고리즘을 사용하여 bytes 라는 ByteArray를 압축합니다.

bytes.compress(CompressionAlgorithm.LZMA);

다음 예제에서는 deflate 알고리즘을 사용하여 압축된 ByteArray를 압축 해제합니다.

bytes.uncompress(CompressionAlgorithm.LZMA);

객체 읽기 및 쓰기

readObject() writeObject() 메서드는 직렬화된 AMF(Action Message Format)로 인코딩된 ByteArray에 대해 객체 읽기/쓰기 작업을 수행합니다. AMF는 Adobe에서 만들어 Netstream, NetConnection, NetStream, LocalConnection 및 공유 객체를 비롯한 다양한 ActionScript 3.0 클래스에 사용되는 고유 메시지 프로토콜입니다.

1바이트 유형 표시자는 뒤에 오는 인코딩된 데이터의 유형을 설명합니다. 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의 두 가지 버전이 있습니다. AMF0은 참조를 통한 복잡한 객체 전송 작업을 지원하며 끝점에서의 객체 관계 복원을 허용합니다. AMF3은 참조를 통해 객체 참조 외에 객체 특징 및 문자열을 보내고 ActionScript 3.0에서 도입된 새로운 데이터 유형을 지원하여 AMF0을 개선합니다. ByteArray.objectEcoding 속성은 객체 데이터를 인코딩하는 데 사용되는 AMF의 버전을 지정합니다. flash.net.ObjectEncoding 클래스는 AMF 버전을 지정하는 상수인 ObjectEncoding.AMF0 ObjectEncoding.AMF3 을 정의합니다.

다음 예제에서는 writeObject() 를 호출하여 ByteArray에 XML 객체를 쓴 다음 Deflate 알고리즘을 사용하여 ByteArray를 압축하고 데스크톱의 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(); 
    } 
}