2012-08-25 100 views
1

這是我'使用壓縮編碼/解壓縮文件:如何在As3中使用ByteArray方法解壓縮LZMA壓縮文件?

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壓縮不夠好。如果不是,請不要給它的一個例子

編輯:?長小時的搜索後,我得到了this 但我不能完全理解示例代碼在它:(有人幫助,任何人?

回答

1

找到一個解決辦法,閃存只有DEFLATEZLIB壓縮算法,所以我不得不等待LZMA更新可能會或可能不會發生,或者創建自己的工具,所以我得到的Python和嘗試一些頸部破小時後弄清楚如何使用它,我終於能夠得到我想要的。

的地方參考:

  1. The python code to decompress LZMA-format swf files
  2. The pylzma source file
1

我只是想添加到您的編輯,以防有人絆倒它提供這對於the link,並得到由困惑格式化,它也有一些奇怪的東西在寫幾個字節兩次,所以這裏是我的重大修改版本(文件部分需要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()