Как распаковать сжатый файл LZMA с помощью метода ByteArray в As3?
Это код, который я использую для сжатия / распаковки файлов:
package {
import flash.display.Sprite;
import flash.events.Event;
import flash.net.FileFilter;
import flash.net.FileReference;
import flash.utils.ByteArray;
public class Compressor extends Sprite
{
private var ref:FileReference;
public function Compressor()
{
ref = new FileReference();
ref.addEventListener(Event.SELECT, load);
ref.browse([new FileFilter("SWF Files", "*.swf")]);
}
private function load(e:Event):void
{
ref.addEventListener(Event.COMPLETE, processSWF);
ref.load();
}
private function processSWF(e:Event):void
{
var swf:ByteArray;
switch(ref.data.readMultiByte(3, "us-ascii"))
{
case "CWS":
swf = decompress(ref.data);
break;
case "FWS":
swf = compress(ref.data);
break;
default:
throw Error("Not SWF...");
break;
}
new FileReference().save(swf);
}
private function compress(data:ByteArray):ByteArray
{
var header:ByteArray = new ByteArray();
var decompressed:ByteArray = new ByteArray();
var compressed:ByteArray = new ByteArray();
header.writeBytes(data, 3, 5); //read the header, excluding the signature
decompressed.writeBytes(data, 8); //read the rest
decompressed.compress();
compressed.writeMultiByte("CWS", "us-ascii"); //mark as compressed
compressed.writeBytes(header);
compressed.writeBytes(decompressed);
return compressed;
}
private function decompress(data:ByteArray):ByteArray
{
var header:ByteArray = new ByteArray();
var compressed:ByteArray = new ByteArray();
var decompressed:ByteArray = new ByteArray();
header.writeBytes(data, 3, 5); //read the uncompressed header, excluding the signature
compressed.writeBytes(data, 8); //read the rest, compressed
compressed.uncompress();
decompressed.writeMultiByte("FWS", "us-ascii"); //mark as uncompressed
decompressed.writeBytes(header); //write the header back
decompressed.writeBytes(compressed); //write the now uncompressed content
return decompressed;
}
}
}
Моя проблема: этот метод не распаковывает сжатые файлы LZMA:(
Может кто-нибудь сказать мне, как реструктурировать приведенный выше код для достижения декомпрессии LZMA и достаточно ли вышеупомянутый код сжатия для LZMA-сжатия? Если нет, приведите пример.
РЕДАКТИРОВАТЬ: После долгих часов поиска, я получил это, но я не совсем понимаю пример кода в нем:(Кто-то поможет, кто-нибудь?
2 ответа
Нашел обходной путь, только Flash DEFLATE
а также ZLIB
алгоритмы сжатия, поэтому мне пришлось ждать LZMA
обновление, которое может произойти, а может и не произойти, или создать свою собственную утилиту, поэтому я получил Python и после нескольких изнурительных попыток выяснить, как его использовать, я наконец смог получить то, что хотел.
Места ссылки:
Я просто хотел добавить к этому ссылку, предоставленную в вашем редакторе, на тот случай, если кто-то запутается в этом и будет столь же смущен форматированием, как и я, у него также есть некоторые странные вещи, связанные с записью нескольких байтов дважды, так что я модифицированная версия (для файловых компонентов требуется AIR). Например, я отошел от побитовых операторов в пользу ByteArray
функции чтения / записи.
Примечание: по крайней мере, в настоящее время AS3 ByteArray.decompress()
поддерживает декомпрессию LZMA, так что я использую это, но он не поддерживает напрямую формат SWF LZMA, только LZMA, поэтому нужно немного поработать, также обратите внимание, что этот код, возможно, можно немного улучшить.
import flash.filesystem.File;
import flash.filesystem.FileStream;
import flash.filesystem.FileMode;
import flash.utils.ByteArray;
function decompressLZMA(idata:ByteArray){
idata.endian = "littleEndian"
var signature:ByteArray = new ByteArray;
//I 0-3 = signature + version
idata.readBytes(signature, 0, 3)
var version:uint = idata.readUnsignedByte()
switch (signature[0]){
case 90: // Z = lzma compressed
var odata:ByteArray = new ByteArray;
odata.endian = "littleEndian"
var i:uint;
//O 0-3 = signature + version
signature[0] = 70 // F = uncompressed
odata.writeBytes(signature)
odata.writeByte(version)
//I 4-7 = swf file length
idata.position = 4
var scriptlen:uint = idata.readUnsignedInt()
//8 = swf header size
scriptlen -= 8
//O 4-7 swf file length
odata.writeUnsignedInt(scriptlen + 8) // Re-add swf header removed earlier
var tdata:ByteArray = new ByteArray;
tdata.endian = "littleEndian"
//I 12 = lzma properties
//I 13-16 = lzma dictionary size
idata.position = 12
//T 0 = lzma properties
//T 1-4 = lzma dictionary size
tdata.writeByte(idata.readByte())
tdata.writeUnsignedInt(idata.readUnsignedInt())
// lzma uncompressed length is stored as LE UI64:
//T 5-8 = uncompressed length
tdata.writeUnsignedInt(scriptlen)
//T 9-12 = uncompressed length continued
tdata.writeUnsignedInt(0)
//16 = LZMA header size
idata.position = 17
//12 = SWF LZMA header size
idata.readBytes(tdata, 13, idata.length-idata.position)
tdata.uncompress(CompressionAlgorithm.LZMA)
odata.writeBytes(tdata)
return odata;
break
}
return idata;
}
var file:File;
var stream:FileStream;
var idata:ByteArray;
var odata:ByteArray;
var path:String
path = File.applicationDirectory.resolvePath('LZMA.swf').nativePath;
file = new File(path);
stream = new FileStream();
stream.open(file, FileMode.READ);
idata = new ByteArray
stream.readBytes(idata)
stream.close()
odata = decompressLZMA(idata)
path = File.applicationDirectory.resolvePath('LZMA_decompressed.swf').nativePath;
file = new File(path);
stream = new FileStream();
stream.open(file, FileMode.WRITE);
stream.writeBytes(odata)
stream.close()