Bu örnek, farklı türlerde birçok dosya içeren basit bir .zip dosyasının nasıl okunacağını gösterir. Bu işlemi her dosyanın meta verilerinden ilgili verileri ayıklayarak, her dosyayı bir ByteArray öğesine genişleterek ve dosyayı masaüstüne yazarak yapar.
Bir .zip dosyasının genel yapısı PKWARE Inc.in belirtimine dayalıdır, bu belirtim
http://www.pkware.com/documents/casestudies/APPNOTE.TXT
adresinde bulunmaktadır. İlki, .zip arşivindeki ilk dosyanın dosya üstbilgisi ve dosya verileridir, ardından her ek dosyanın dosya üstbilgisi ve dosya veri çifti gelir. (Dosya üstbilgisinin yapısı daha ileride anlatılmaktadır.) İkincisi, .zip dosyası isteğe bağlı olarak bir veri tanımlayıcı kaydı içerir (genellikle çıktı zip dosyası diske kaydedilmek yerine bellekte oluşturulduğunda). Üçüncü olarak, birçok ilave isteğe bağlı öğe bulunmaktadır: arşiv şifre çözme üstbilgisi, arşiv ek veri kaydı, merkezi dizin yapısı, Zip64 merkezi dizin kaydının sonu, Zip64 merkezi dizin bulucunun sonu ve merkezi dizin kaydının sonu.
Bu örnekteki kod yalnızca klasör içermeyen zip dosyalarının ayrıştırılması için yazılmıştır ve veri tanımlayıcı kayıtları beklemez. Son veri dosyasını izleyen tüm bilgileri yok sayar.
Her dosya için dosya üstbilgi biçimi şöyledir:
dosya üstbilgisi imzası
|
4 bayt
|
gerekli sürüm
|
2 bayt
|
genel amaçlı bit bayrağı
|
2 bayt
|
sıkıştırma yöntemi
|
2 bayt (8=DEFLATE; 0=SIKIŞTIRILMAMIŞ)
|
dosyanın son değiştirilme zamanı
|
2 bayt
|
dosyanın son değiştirilme tarihi
|
2 bayt
|
crc-32
|
4 bayt
|
sıkıştırılmış boyut
|
4 bayt
|
sıkıştırılmamış boyut
|
4 bayt
|
dosya adı uzunluğu
|
2 bayt
|
ek alan uzunluğu
|
2 bayt
|
dosya adı
|
değişken
|
ek alan
|
değişken
|
Dosya üstbilgisinin ardından gerçek dosya verileri gelir, bu veriler sıkıştırma yöntemi bayrağına bağlı olarak sıkıştırılmış veya sıkıştırılmamış olabilir. Dosya verileri sıkıştırılmamışsa bayrak 0'dır (sıfır), DEFLATE algoritması kullanılarak sıkıştırılmışsa 8'dir veya diğer sıkıştırma algoritmaları kullanılmışsa başka bir değerdir.
Bu örneğin kullanıcı arabirimi bir etiket ve metin alanından oluşur (
taFiles
). Uygulama aşağıdaki bilgileri .zip dosyasında karşılaştığı her dosyanın metin alanına yazar: dosya adı, sıkıştırılmış boyut ve sıkıştırılmamış boyut. Aşağıdaki MXML belgesi uygulamanın Flex versiyonuna ait kullanıcı arabirimini açıklıyor:
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" creationComplete="init();">
<mx:Script>
<![CDATA[
// The application code goes here
]]>
</mx:Script>
<mx:Form>
<mx:FormItem label="Output">
<mx:TextArea id="taFiles" width="320" height="150"/>
</mx:FormItem>
</mx:Form>
</mx:WindowedApplication>
Programın başlangıcı aşağıdaki görevleri gerçekleştirir:
-
Gerekli sınıfları içeri aktarır
import flash.filesystem.*;
import flash.utils.ByteArray;
import flash.events.Event;
-
Kullanıcı arabirimini tanımlar Flash için
import fl.controls.*;
//requires TextArea and Label components in the Library
var taFiles = new TextArea();
var output = new Label();
taFiles.setSize(320, 150);
taFiles.move(10, 30);
output.move(10, 10);
output.width = 150;
output.text = "Contents of HelloAir.zip";
addChild(taFiles);
addChild(output);
-
bytes
ByteArray öğesini tanımlar
var bytes:ByteArray = new ByteArray();
-
Dosya üstbilgisinden meta verileri saklamak için değişkenleri tanımlar
// variables for reading fixed portion of file header
var fileName:String = new String();
var flNameLength:uint;
var xfldLength:uint;
var offset:uint;
var compSize:uint;
var uncompSize:uint;
var compMethod:int;
var signature:int;
-
.zip dosyasını temsil etmek için File (
zfile
) ve FileStream (
zStream
) nesnelerini tanımlar ve dosyaların ayıklandığı .zip dosyasının konumunu belirtir—masaüstü dizininde “HelloAIR.zip” adlı bir dosya.
// File variables for accessing .zip file
var zfile:File = File.desktopDirectory.resolvePath("HelloAIR.zip");
var zStream:FileStream = new FileStream();
Flex'te, program kodu
init()
yöntemiyle başlar ve buna kök
mx:WindowedApplication
için
creationComplete
işleyicisi etiketi adı verilir.
// for Flex
private function init():void
{
Program .zip dosyasını OKUMA modunda açarak başlar.
zStream.open(zfile, FileMode.READ);
Ardından, sayısal alanların bayt sıralamasında en düşük değerli baytın önce geldiğini göstermek için
bytes
öğesinin
endian
özelliğini
LITTLE_ENDIAN
olarak ayarlar.
bytes.endian = Endian.LITTLE_ENDIAN;
Sonra
while()
ifadesi, dosya akışındaki geçerli konum dosya boyutundan büyük veya dosya boyutuna eşit olana kadar devam eden bir döngü başlatır.
while (zStream.position < zfile.size)
{
Döngüdeki ilk ifade dosya akışının ilk 30 baytını ByteArray
bytes
öğesine okur. İlk 30 bayt, ilk dosya üstbilgisinin sabit boyutlu parçasını oluşturur.
// read fixed metadata portion of local file header
zStream.readBytes(bytes, 0, 30);
Sonra kod, 30 baytlık üstbilginin ilk baytlarından bir tam sayı (
signature
) okur. ZIP biçimi tanımı, her dosya üstbilgi imzasının onaltılık değer
0x04034b50
olduğunu belirtir; imza farklıysa bu, kodun, .zip dosyasının dosya kısmının ötesine taşındığı ve ayıklanacak dosya olmadığı anlamına gelir. Bu durumda kod, bayt sırasının sonunu beklemek yerine hemen
while
döngüsünden çıkar.
bytes.position = 0;
signature = bytes.readInt();
// if no longer reading data files, quit
if (signature != 0x04034b50)
{
break;
}
Kodun sonraki kısmı üstbilgi baytını uzaklık konumu 8'de okur ve değeri
compMethod
değişkeninde saklar. Bu bayt, bu dosyayı sıkıştırmak için kullanılan sıkıştırma yöntemini gösteren bir değer içerir. Birçok sıkıştırma yöntemi kullanılabilir, ancak uygulamada neredeyse tüm .zip dosyaları DEFLATE sıkıştırma algoritmasını kullanmaktadır. Geçerli dosya DEFLATE sıkıştırmayla sıkıştırıldıysa
compMethod
8'dir; dosya sıkıştırılmamışsa,
compMethod
0'dır.
bytes.position = 8;
compMethod = bytes.readByte(); // store compression method (8 == Deflate)
İlk 30 baytın ardından, üstbilginin dosya adını ve büyük olasılıkla ek bir alan içeren üstbilginin değişken uzunluklu kısmı gelir. Değişken
offset
bu kısmın boyutunu saklar. Boyut, uzaklık 26 ve 28'deki üstbilgilerden okunan dosya adı uzunluğu ve ek alan uzunluğu toplanarak hesaplanır.
offset = 0; // stores length of variable portion of metadata
bytes.position = 26; // offset to file name length
flNameLength = bytes.readShort(); // store file name
offset += flNameLength; // add length of file name
bytes.position = 28; // offset to extra field length
xfldLength = bytes.readShort();
offset += xfldLength; // add length of extra field
Sonra program
offset
değişkeninde saklanan bayt sayısı için dosya üstbilgisinin değişken uzunluklu kısmını okur.
// read variable length bytes between fixed-length header and compressed file data
zStream.readBytes(bytes, 30, offset);
Program, dosya adını üstbilginin değişken uzunluk kısmından okur ve dosyanın sıkıştırılmış (zip) ve sıkıştırılmamış (orijinal) boyutlarıyla birlikte metin alanında görüntüler.
// Flash version
bytes.position = 30;
fileName = bytes.readUTFBytes(flNameLength); // read file name
taFiles.appendText(fileName + "\n"); // write file name to text area
bytes.position = 18;
compSize = bytes.readUnsignedInt(); // store size of compressed portion
taFiles.appendText("\tCompressed size is: " + compSize + '\n');
bytes.position = 22; // offset to uncompressed size
uncompSize = bytes.readUnsignedInt(); // store uncompressed size
taFiles.appendText("\tUncompressed size is: " + uncompSize + '\n');
// Flex version
bytes.position = 30;
fileName = bytes.readUTFBytes(flNameLength); // read file name
taFiles.text += fileName + "\n"; // write file name to text area
bytes.position = 18;
compSize = bytes.readUnsignedInt(); // store size of compressed portion
taFiles.text += "\tCompressed size is: " + compSize + '\n';
bytes.position = 22; // offset to uncompressed size
uncompSize = bytes.readUnsignedInt(); // store uncompressed size
taFiles.text += "\tUncompressed size is: " + uncompSize + '\n';
Örnek, dosyanın geri kalanını sıkıştırılmış boyut tarafından belirtilen uzunluk için dosya akışından
bytes
öğesine okur ve ilk 30 bayttaki dosya üstbilgisinin üzerine yazar. Dosya sıkıştırılmış olmasa bile sıkıştırılmış boyut doğrudur, çünkü bu durumda sıkıştırılmış boyut dosyanın sıkıştırılmamış boyutuna eşittir.
// read compressed file to offset 0 of bytes; for uncompressed files
// the compressed and uncompressed size is the same
if (compSize == 0) continue;
zStream.readBytes(bytes, 0, compSize);
Sonra örnek, sıkıştırılmış dosyayı genişletir ve çıktı dosyası akışına yazmak için
outfile()
işlevini çağırır.
outfile()
öğesine dosya verilerini içeren dosya adını ve bayt sırasını iletir.
if (compMethod == 8) // if file is compressed, uncompress
{
bytes.uncompress(CompressionAlgorithm.DEFLATE);
}
outFile(fileName, bytes); // call outFile() to write out the file
Daha önce bahsedilen örnekte,
bytes.uncompress(CompressionAlgorithm.DEFLATE)
öğesi yalnızca AIR uygulamalarında çalışır. Hem AIR hem de Flash Player için sönmüş verinin sıkıştırmasını açmak için ByteArray öğesinin
inflate()
işlevini çağırın.
Kapatma ayraçları,
outFile()
yöntemi haricinde,
while
döngüsünün,
init()
yönteminin ve uygulama kodunun sonunu gösterir. Çalıştırma
while
döngüsünün başlangıcına kadar geriye doğru ilerler ve başka bir dosyayı ayıklayarak veya son dosya işlenmişse .zip dosyasını işlemeyi sonlandırarak .zip dosyasında bulunan sonraki baytları işlemeye devam eder.
} // end of while loop
} // for Flex version, end of init() method and application
outfile()
işlevi bir çıktı dosyasını, dosyaya
filename
parametresi tarafından sağlanan ismi vererek masaüstünde YAZMA modunda açar. Ardından
data
parametresindeki dosya verilerini çıktı dosyası akışına (
outStream
) yazar ve dosyayı kapatır.
// Flash version
function outFile(fileName:String, data:ByteArray):void
{
var outFile:File = File.desktopDirectory; // destination 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();
}
private 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();
}