ストリームがJavaで圧縮されているかどうかを検出する最良の方法

StackOverflow https://stackoverflow.com/questions/1809007

  •  05-07-2019
  •  | 
  •  

質問

圧縮されたデータが含まれている java.io.InputStream を見つける最良の方法は何ですか?

役に立ちましたか?

解決

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

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

他のヒント

はじめに

すべての答えは5歳なので、今日何が起こっているのかを書き留める義務があります。ストリームの魔法のバイトを読むべきだと真剣に思っています!これは低レベルのコードです。一般的には避けてください。

単純な回答

mikuの書き込み:

  

ZipInputStreamを介してストリームを読み取ることができる場合、圧縮する必要があります。

はい、ただし ZipInputStream の場合" readed canquote"は、 .getNextEntry()の最初の呼び出しがnull以外の値を返すことを意味します。キャッチなどは例外ではありません。そのため、マジックバイトの解析の代わりに、次のことができます。

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

これで完了です!

一般的な解凍の考え方

一般に、ストリームを使用するよりも[un] zipを使用してファイルを操作する方がはるかに便利であると思われました。いくつかの便利なライブラリがあり、さらにZipFileにはZipInputStreamよりも多くの機能があります。 zipファイルの処理については、次を参照してください。良いことJavaライブラリを使用してファイルをzip / unzipしますか

コードサンプル

アプリケーションでストリームのみを使用する必要がありました。これが私が解凍用に書いたメソッドです:

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;
}

ストリームの最初の4バイトが、ZIPファイル内のすべてのファイルを処理するローカルファイルヘッダーを開始するローカルファイルヘッダー署名であることを確認できます< a href = "http://www.pkware.com/documents/casestudies/APPNOTE.TXT" rel = "noreferrer">仕様に記載されているとおり、 50 4B 03 04

これが機能することを示す小さなテストコード:

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);
}

この出力を送ってください:

50 4B 3 4 

あまりエレガントではないが、信頼性が高い:

ZipInputStream 、圧縮する必要があります。

マジックナンバーを確認するのは適切な選択肢ではない可能性があります。

Docxファイルも同様のマジック番号50 4B 3 4を持っています

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top