1

これは私がファイルを圧縮/解凍するために使用しているコードです:

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圧縮に十分かどうかを教えてもらえますか?そうでない場合は、例を挙げてください。

編集:長い時間の検索の後、私はこれを手に入れまし たが、その中のサンプルコードを完全に理解することはできません:(助けてください、誰か?

4

2 に答える 2

1

回避策が見つかりました。Flashには圧縮アルゴリズムしかDEFLATEありません。更新ZLIBを待つ必要がありました。LZMA更新を待つか、独自のユーティリティを作成する必要がありました。Pythonを入手し、数時間かけて使用方法を理解しました。ようやく欲しいものを手に入れることができました。

参照場所:

  1. LZMA形式のswfファイルを解凍するPythonコード
  2. pylzmaソースファイル
于 2012-08-27T18:06:48.917 に答える
1

誰かがつまずいて、私と同じようにフォーマットに混乱した場合に備えて、編集で提供されたリンクに関してこれに追加したかっただけです。また、数バイトを2回書き込むことで奇妙なことが起こっているので、これが私のそれの修正バージョン(ファイル部分にはAIRが必要です)。ByteArrayたとえば、読み取り/書き込み関数を優先して、ビット演算子から離れました。

注:少なくとも最近では、AS3ByteArray.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()
于 2016-09-30T02:07:26.563 に答える