前回、zipの展開方法を記述しましたので、今度は圧縮方法です。
例の如く、実際の圧縮には ByteArray.compress() を用いています。
基本的に、動作の確認はWindowsでしかやっておりません。
ただし、作成したzipファイルがLinuxでのunzipコマンドで展開できることは確認しております。
Zipの圧縮方法
[AS]
import com.coltware.commons.zip.*;
import flash.filesystem.*;
public function zip():void{
zipWriter = new ZipFileWriter();
zfile = File.desktopDirectory.resolvePath(“sample.zip”);
var file1:File = File.desktopDirectory.resolvePath(“sample.doc”);
zipWriter.addFile(file1,”sample.doc”);
// 空のディレクトリを追加する場合には、以下のようにする
// 空でない場合は、直接下のファイルのようにしてしまえば問題ありません。
zipWriter.addDirectory(“フォルダ1″);
var file2:File = File.desktopDirectory.resolvePath(“sample1.doc”);
zipWriter.addFile(file2,”フォルダ2/読んでください.doc”);
// これを忘れないでください。ファイルとしては作成されますが、
// ここで最後の情報を記述していますので、
// おかしなファイルになってしまいます。
zipWriter.close();
}
[/AS]
また、パスのセパレータ( “/”ってやつ)は、OSに関係なく”/”にしてください。
これは、Zipフォーマットのルールですが。
また、ファイルの先頭に”/”をつけないでください。
Windowsでは見えなくなります。(linux unzipの場合にはワーニングがでて無視されるようです。)
Linux用にZipファイルを作成したい場合
[AS]
zipWriter = new ZipFileWriter(ZipFileWriter.HOST_UNIX);
//
// デフォルトは ZipFileWriter.HOST_WIN です。
//
[/AS]
のようにしてください。
これで、日本語ファイル名がUTF-8になります。
また、ファイルのパーミッションを設定したい場合には、
[AS]
// ディレクトリのモード(空のディレクトリを追加した場合)
zipWriter.setDirMode(“0777″);
// ファイルのモード
zipWriter.setFileMode(“0777″);
[/AS]
のように設定してください。
ここは文字列の8進数で設定してください。
設定後、すべてこのパーミッションが適用されます。
ファイルからではなくByteArrayデータから登録したい
[AS]
public function addBytes(data:ByteArray,filename:String,bytes:ByteArray,date:Date = null):void
[/AS]
というメソッドがありますので、こちらを利用ください。
実際にaddFileも、この関数を使っています。
date は、最終変更日時ですが、何も入れなければ”今”の時間が入ります。
これを書いていて、Zipの展開には非同期処理があるのですが、圧縮には非同期処理をつけ忘れたことに気が付きました。
Fzipとの違い
- 日本語ファイルの対応
MACでZipしたファイルをWinで解凍すると文字化けするという問題の対応などもしてあります。
日本語環境で、Windowsで作られたと思われるZipファイルはSJIS, それ以外はUTF-8がファイル名の文字コードになります。
ただし、書き込み時には作成されるホストOSを選ぶようにします。
文字コード以外にも、考慮する部分が出てきますので・・・ - 読み込み時に情報レコードから先に読み大きなファイルでも少ない時間で情報を取得
ファイルを最後から読んでいます。
まあ、このあたりはAIRだからこそできるわけですが・・・・
ActionScriptってファイルの読み込みが遅いんですよね。 - ファイルの属性対応
いわゆる、そのファイルがディレクトリか、ファイルかなど。また、UNIX系の場合にはパーミッションなど。
このあたりが設定されていないと、うまく解凍できないものもありますので・・・ - 非同期対応
解凍していると、固まってしまうのですがこれを回避しています。
ただし、圧縮ではありません。(ただ忘れただけですので作ります)
ダウンロードは前回の記事を見てください。



いつも参考にさせてもらってます。
以前から利用させてもらっているのですが
500MB以上のファイルを圧縮させようとしてるのですが
下記のようなERRORで悩んでおります。
(400MB等のファイルは問題ないのですが)
何か解ればご教授お願いします。
Error: Error #1000: The system is out of memory.
at flash.utils::ByteArray/_compress()
at flash.utils::ByteArray/compress()
at com.coltware.airxzip::ZipFileWriter/internalAddBytes()[/home/xxxxx/public/google_code/airxzip/branches/v1.0/airxzip/src/com/coltware/airxzip/ZipFileWriter.as:375]
at com.coltware.airxzip::ZipFileWriter/addFile()[/home/xxxxx/public/google_code/airxzip/branches/v1.0/airxzip/src/com/coltware/airxzip/ZipFileWriter.as:176]
ありがとうございます。
さすがに、100M単位のファイルを圧縮されるほどの使い方はされるいる方がいるとは思いませんでした。
The system is out of memory.
とあるので、メモリ不足なのだと思います。
ただ、その原因としてですが、上でも書いたようにそこまでの使い方を想定していなかったのと、
私自身Flashについてよくわかっていなかった(というか今でもたたあるのですが・・・)ので、
1つのファイルの圧縮をByteArrayのcompress() という関数でやってしまっているからだと思います。
現時点では、そこまでの容量はご遠慮くださいというよりないかなと・・・・
ただ、400Mなどでできたとしても、画面が固まるなどのことが起きてしまって、
使い物にならない状態にはならないのでしょうか?
このあたりの現状もご参考までに教えていただけたらうれしく思います。
実際に直すとしたら、ファイルをもっと細かく分割して分割処理をしなければならなくなるとはおもいます。
返事ありがとうございます。
ByteArrayでこけてるのだろうと想定してました。
ご指摘の通り画面が固まる現象もでております。
圧縮中に動画再生などでごまかそうかと・・・試行錯誤中です。
とりあえず、いろいろ試してみます。
有難うござました。
そこまでして使っていただけることは大変うれしく思います。
できるかどうか、確証はもてませんが、
ファイルを分割して圧縮してみることが可能かみてみるようにしてみます。
(分割すると、圧縮ロジックまで自作するはめになるかもしれません。)
ところで、
500M のファイルというとかなり大きいのですが、もし動画とかだったりすると、
あまり圧縮しても、意味がないきがします。
もしかしたら、単純にZIPファイルとして含めたいだけで、圧縮はいらないならば、
変更も可能かと思いますが・・・・
利用させて頂いてる処理は
複数のデザインデータを一つのZIPファイルに圧縮したいのが目的でした。
デザインデータはAdobeさんPSD,AI,EPSなどのファイルなど、かなりな容量です((+_+))
複数ファイルを単純にワンファイルのZIP化できればOKなのですが
やはり圧縮して容量を少しでも下げれればと思っています。
なるほど。
デザインデータはでかいですよね。
やはり、1つのファイルが400Mを超えているものがあるのでしょうか?
というのも、きっかけがたまたま compress() であって、メモリをどこかで食いつぶしているところが別にあるのかなと思いまして。
ちなみに、ファイルを分割して圧縮することはちょっと現実的ではなさそうそうです。
圧縮ロジックを自分で作成するか、
もしくは、
分割して圧縮データを読んで管理データを探し、書き換えるてから連結する。
(つまり、解凍処理を実装することと同じ)
となるために、AS3ではやはり、ByteArray.compress() しかないかなと。
なので、ファイルサイズが実際のcompressに渡ってしまいます。
すいません。
ちなみに、まだまだ先の話にはなるのですが、私も大量のデータや処理をFlash/AIRのUIを使ってできるローカルアプリを作りたいと思いまして、しかし、どうしてもFlash/AIRでは処理で融通が利かないといいますが、回避どころがわからないといいますか・・・
という理由がありまして、ローカルでJavaブリッジを使って、そちらで大量処理はさせるという方法をとろうかなと考えています。
こういうソリューションが可能だとしたら、問題は解決できますか?
(それとも、Pure AIRでやる必要性がどうしてもありますか?)
参考までに意見をもらえたらと思います。
やはり今回の案件(大容量データを扱う)件は、
coltwareさんの回避策のとおり、javaへ処理を渡して回避させました。
やはりjavaしかないのかなと・・・
AIR2.0のNativeProcessでjavaを処理させました。
インストーラーがAIRじゃなくなってしまうのが残念です。
理想はAIRのみで全て完結したかったのですが
やはり容量が大きいファイルだと固まる現象が出てしまいますので
ユーザーの印象もありますし。
大容量じゃない場合は今後も利用させてもらいます。