3

zip ファイルをダウンロードしてローカルで解凍するプロジェクトに取り組んでいます。私が直面している問題は、解凍プロセスが 5% の確率で機能することです。

時々動作するため、この時点では謎ですが、ほとんどの場合、データまたはcrcエラーがスローされます。zip ファイルが変更されていない場合でも、エラーが切り替わります。

さまざまなツールで作成された zip ファイルを試してみましたが、形式が間違っているのではないかと考えています。しかし、役に立たない。ターミナルで作成された zip でさえ機能しません。

これが私の解凍コードです:

try {
    String _location = model.getLocalPath();
    FileInputStream fin = new FileInputStream(localFile);
    ZipInputStream zin = new ZipInputStream(fin);
    ZipEntry ze = null; 
    byte[] buffer = new byte[1024];
    while((ze = zin.getNextEntry()) != null) {
        if(_cancel) break; 

        System.out.println("unzipping " + ze.getName());

        if(ze.isDirectory()) {
            File f = new File(_location + ze.getName());
            f.mkdirs();
        } else { 

            FileOutputStream fout = new FileOutputStream(_location + ze.getName());
            for(int c = zin.read(buffer); c > 0; c = zin.read(buffer)) {
                fout.write(buffer,0,c);
            }
            zin.closeEntry();
            fout.close();
        }
    }
    zin.close();

    if(_cancel) {
        handler.post(dispatchCancel);
        return;
    }

} catch(Exception e) {
    System.out.println("UNZIP ERROR!");
    System.out.println(e.getMessage());
    System.out.println(e.toString());
    e.printStackTrace();
}

そして、これが私が通常zipファイルを作成する方法です。

$>zip -r myzip.zip myzip/

2 つのエラー出力を次に示します。

java.util.zip.ZipException: CRC mismatch
    at java.util.zip.ZipInputStream.readAndVerifyDataDescriptor(ZipInputStream.java:209)
    at java.util.zip.ZipInputStream.closeEntry(ZipInputStream.java:173)
    at com.XX.XX.XXIssueDownloader$7.run(XXIssueDownloader.java:222)
    at java.lang.Thread.run(Thread.java:1020)

java.util.zip.ZipException: data error
    at java.util.zip.ZipInputStream.read(ZipInputStream.java:336)
    at java.io.FilterInputStream.read(FilterInputStream.java:133)
    at com.XX.XX.XXIssueDownloader$7.run(XXIssueDownloader.java:219)
    at java.lang.Thread.run(Thread.java:1020)

これらのエラーが発生する理由を知っている人はいますか? 私はこれらでどこにも行きません。

4

1 に答える 1

6

Zipファイルをロードするときに非常に重要なことが2つあります。

  1. Accept-Encoding:ヘッダーを含まないリクエストメソッドを使用していることを確認してください。リクエストに含まれている場合、レスポンスはzipファイルではなく、gzipで圧縮されたzipファイルです。したがって、ダウンロード中にディスクに直接書き込んでいる場合、実際にはzipファイルにはなりません。次のようなものを使用して、zipファイルをロードできます。

    URL url = new URL(remoteFilePath);
    URLConnection connection = url.openConnection();
    InputStream in = new BufferedInputStream(connection.getInputStream());
    FileOutputStream f = new FileOutputStream(localFile);
    
    //setup buffers and loop through data
    byte[] buffer = new byte[1024];
    long total = 0;
    long fileLength = connection.getContentLength();
    int len1 = 0;
    while((len1 = in.read(buffer)) != -1) {
            if(_cancel) break;
            total += len1;
            _Progress = (int) (total * 100 / fileLength);
            f.write(buffer,0,len1);
            handler.post(updateProgress);
    }
    f.close();
    in.close();
    
  2. 入力ストリームと出力ストリームを使用する場合は、read(buffer)またはwrite(buffer)メソッドを使用しないでください。read/ write(buffer、0、len)を使用する必要があります。そうしないと、書き込みまたは読み取りを行っているものに、ガベージデータが含まれる可能性があります。前者(read(buffer))は常にバッファー全体を読み取りますが、実際には完全なバッファーがない場合があります。たとえば、ループの最後の反復で512バイトしか読み取られなかった場合などです。したがって、ファイルを解凍する方法は次のとおりです。

    String _location = model.getLocalPath();
    FileInputStream fin = new FileInputStream(localFile);
    ZipInputStream zin = new ZipInputStream(fin);
    ZipEntry ze = null; 
    
    while((ze = zin.getNextEntry()) != null) {
            if(_cancel) break;  
            System.out.println("unzipping " + ze.getName());
            System.out.println("to: " + _location + ze.getName());
            if(ze.isDirectory()) {
                    File f = new File(_location + ze.getName());
                    f.mkdirs();
            } else { 
                    byte[] buffer2 = new byte[1024];
                    FileOutputStream fout = new FileOutputStream(_location + ze.getName());
                    for(int c = zin.read(buffer2); c > 0; c = zin.read(buffer2)) {
                            fout.write(buffer2,0,c);
                    }
                    zin.closeEntry();
                    fout.close();
            }
    }
    zin.close();
    
于 2012-06-20T18:50:28.993 に答える