2009-11-27 9 views

答えて

21

ZIPフォーマットのmagic bytesは、50 4Bです。ストリームをテストすることができます(markresetを使用する必要があります - bufferにする必要があります)が、これは100%信頼できるアプローチであるとは思わないでしょう。 PKという文字で始まるUS-ASCIIでエンコードされたテキストファイルと区別する方法はありません。

の方法では、ストリームを開く前にメタデータをコンテンツ形式に提供し、適切に処理することができます。

5

非常にエレガントな、しかし信頼性がない:ストリームがZipInputStream経由で読み取ることができる場合

、それがZIP形式でなければなりません。

+1

それはちょっといいとは思わない。破損したZIPストリームではありませんか? – Fedearne

+10

@fedearne:破損したzipストリームがzipストリームですか? – GvS

+2

私は同意します:ZipInputStreamがそれを読むことができない場合、それはZipファイルであることを意味していません。右? –

6

あなたは、ストリームの最初の4つのバイトが50 4B 03 04すべきZIPファイル内のすべてのファイルを移行ローカルファイルヘッダas shown in the spec hereを開始ローカルファイルヘッダ署名であることを確認できました。

少しテストコードは、これは動作する例を示します。すべての答えは、私が感じる5歳なので

50 4B 3 4 
+1

私は同じアイディアを持っていましたが(恥ずかしながら、信頼できるWikipediaですが)、これは信頼できるメカニズムではないようです:_ "実装者は、ZIPファイルがこの署名マーキングデータ記述子の有無にかかわらず互換性を保証するためにZIPファイルを読むときにどちらのケースも考慮する必要があります。 "_ – McDowell

+1

これは一般的な見解に当てはまりますが、ZipInputStreamがZipEntryオブジェクトを主張しているので、署名がない場合は失敗します。 –

+1

zipファイル(Microsoft Windows実行ファイルなど)の前にランダムなジャンクを付けることができます。ローカルヘッダーでストリーミングするのではなく、セントラルディレクトリを使用する場合にのみ機能します。 FWIW、Java PlugInとWebStartは中央ディレクトリを使用しますが、最初の4バイトもチェックします(GIARを参照)。 –

35

はじめ

byte[] buffer = new byte[4]; 

try { 
    ZipOutputStream zos = new ZipOutputStream(new FileOutputStream("so.zip")); 
    ZipEntry ze = new ZipEntry("HelloWorld.txt"); 
    zos.putNextEntry(ze); 
    zos.write("Hello world".getBytes()); 
    zos.close(); 

    FileInputStream is = new FileInputStream("so.zip"); 
    is.read(buffer); 
    is.close(); 
} 
catch(IOException e) { 
    e.printStackTrace(); 
} 

for (byte b : buffer) { 
    System.out.printf("%H ",b); 
} 

が私にこの出力を与えました書き留める義務、今日起こっていること。私は真剣にストリームの魔法のバイトを読むべきであると疑う!それは低レベルのコードなので、一般的に避けるべきです。

単純な答え

ミクは書いている:

ストリームはZipInputStreamを経由して読み取ることができれば、それはzip形式で圧縮されなければなりません。

はい、しかしZipInputStreamの場合に「読み取ることができる」.getNextEntry()の最初の呼び出しが非ヌル値を返すことを意味します。例外をキャッチすることはありません。だから、代わりにあなたを解析する魔法のバイトだけで行うことができます。

boolean isZipped = new ZipInputStream(yourInputStream).getNextEntry() != null; 

そして、それはそれです!一般的に考え

を解凍

一般的には、[UN]ストリームよりも、ビュンながら、ファイルを操作するためにはるかに便利だと思われました。便利なライブラリがいくつかありますが、ZipFileにはZipInputStreamよりも多くの機能があります。 zipファイルの取り扱いについては、こちらを参照してください。What is a good Java library to zip/unzip files?ファイルで作業することができれば、より効果的です!私は唯一のストリームで動作するように自分のアプリケーションに必要な

コードサンプル

。だから私は解凍のために書いた方法です:

import org.apache.commons.io.IOUtils; 
import java.util.zip.ZipEntry; 
import java.util.zip.ZipInputStream; 

public boolean unzip(InputStream inputStream, File outputFolder) throws IOException { 

    ZipInputStream zis = new ZipInputStream(inputStream); 

    ZipEntry entry; 
    boolean isEmpty = true; 
    while ((entry = zis.getNextEntry()) != null) { 
     isEmpty = false; 
     File newFile = new File(outputFolder, entry.getName()); 
     if (newFile.getParentFile().mkdirs() && !entry.isDirectory()) { 
      FileOutputStream fos = new FileOutputStream(newFile); 
      IOUtils.copy(zis, fos); 
      IOUtils.closeQuietly(fos); 
     } 
    } 

    IOUtils.closeQuietly(zis); 
    return !isEmpty; 
} 
+1

'ZipOutputStream'が正しく終了していないか閉じている状況があります。これは、無効なため、新しいZipFile(f)に解析されたときに結果ファイルが' IOException'をスローすることを意味します。 zipファイルが他の目的のために無効であっても、上記は失敗しません。 –

0

マジックナンバーをチェックするのは正しい選択ではないかもしれません。

Docxファイルも同様のマジックナンバー50 4B 3 4

+2

これは、docxファイルがzipファイルであるためです。 – tak3shi

関連する問題