4

こんにちは、私は zip 形式にまったく慣れていません。Java の util 実装を使用してファイルを解凍しましたが、ファイルを開こうとするたびに ZipException がスローされます。ファイルが破損しているかどうかを確認しましたが、winRar を使用して開くことができるからではありません。

だから私は先に進み、appache.commons.vfsパッケージで同じことをしようとしましたが、それも失敗しました。

最後の試みとして、ライブラリ 7-zip-jbinding を試してみました。これは Zip アーカイブの内容を読み取ることができますが、抽出することはできません。

ネイティブ Java 実装のコードは次のとおりです。

BufferedOutputStream dest = null;
    FileInputStream fis = new FileInputStream(archive);
    ZipInputStream zis = new ZipInputStream(new BufferedInputStream(fis));
    ZipEntry entry;
    File destFile;

    destinationDir.mkdir();

    while ((entry = zis.getNextEntry()) != null) {

        String currentfileName = entry.getName();
        destFile = new File(destinationDir, currentfileName);
        File destinationParent = destFile.getParentFile();

        destinationParent.mkdirs();

        if (!entry.isDirectory()) {
            int currentByte;
            byte data[] = new byte[BUFFER_SIZE];

            FileOutputStream fos = new FileOutputStream(destFile);
            dest = new BufferedOutputStream(fos, BUFFER_SIZE);

            while ((currentByte = zis.read(data, 0, BUFFER_SIZE)) != -1) {
                dest.write(data, 0, currentByte);
            }
            dest.flush();
            dest.close();

        }
    }
    fis.close();
    zis.close(); 

apache commons vfsの私のコード

 public void unpack(final File outputDir,URI packLocation) throws IOException
   {
 this.packLocation = packLocation;
 this.fileSystemManager = VFS.getManager();

 outputDir.mkdirs();

  final FileObject packFileObject =   fileSystemManager.resolveFile(packLocation.toString());
  try
  {
     final FileObject zipFileSystem = fileSystemManager.createFileSystem(packFileObject);
     try
     {
        fileSystemManager.toFileObject(outputDir).copyFrom(zipFileSystem, new AllFileSelector());
     }
     finally
     {
        zipFileSystem.close();
     }
  }
  finally
  {
     packFileObject.close();
  }
 }

私が欠けていることが非常に明白なものはありますか?また、zip ファイルをファイル システムに抽出するために 7-zip-jbinding を使用したことがある場合は、その方法を教えてください。

編集1:

そのファイルのMac端末で解凍を実行しているときに、次の警告が表示されました

警告: zipfile の先頭または内部に 84 バイトの余分なバイトがあります。これは Zip 入力ストリームに何らかの影響を与える可能性がありますか?

編集2:

zip ファイル内の余分なバイトは、zip 入力ストリームを台無しにしているように見えました..端末で unzip を使用すると、zip ファイルに追加された余分なバイト数が表示されます。RandomAccessFile を使用して (n) バイトをスキップすると、Zip 入力ストリームが正常に動作し始めました..あとは、Zip ファイルの余分なバイトを削除する方法を見つけるだけです..

編集されたコードは、将来それから利益を得る人のために以下に貼り付けられます.

    final int BUFFER_SIZE = 1024;

    RandomAccessFile randomAccessFile = new RandomAccessFile(archive, "r");
    randomAccessFile.skipBytes(84); // The extra bytes 

    FileChannel channel = randomAccessFile.getChannel();

    BufferedOutputStream dest = null;
    ZipInputStream zis = new ZipInputStream(new BufferedInputStream(Channels.newInputStream(channel)));
    ZipEntry entry;
    File destFile;

    destinationDir.mkdir();

    while ((entry = zis.getNextEntry()) != null) {

        String currentfileName = entry.getName();
        destFile = new File(destinationDir, currentfileName);
        File destinationParent = destFile.getParentFile();

        destinationParent.mkdirs();

        if (!entry.isDirectory()) {
            int currentByte;
            byte data[] = new byte[BUFFER_SIZE];

            FileOutputStream fos = new FileOutputStream(destFile);
            dest = new BufferedOutputStream(fos, BUFFER_SIZE);
            while ((currentByte = zis.read(data, 0, BUFFER_SIZE)) != -1) {
                dest.write(data, 0, currentByte);
            }
            dest.flush();
            dest.close();

        }
    }
    zis.close();

誰かが余分なバイトをスキップする方法を知っているなら、私はすべての耳です:)

4

2 に答える 2

2

最後に、友人の助けを借りて問題を解決しました。

空のバイトをスキップする簡単な方法は、'PK' 署名に遭遇するまで読み続けることです。したがって、プログラムでは、入力ストリームは「PK」に到達するまでバイトを読み取り、その後、Zip inputStream を初期化し、それに続くバイトのストリームを渡します。

以下は、手早く汚い方法です。これよりも洗練された解決策があるでしょう..しかし、今のところこれでうまくいきます.

 InputStream zipStarterStream, emptyBytecountStream;
    ZipInputStream zis;
    int BUFFER = 2048;

    /* Primary Checking to see if there is a zip file */
    File file = new File(filePath);
    if (file.exists()) {
        System.out.println("Zip found");
    } else {
        System.out.println("Zip Not found");
        return;
    }
    try {
        emptyBytecountStream = new FileInputStream(filePath);
        Charset encoding = Charset.defaultCharset();
        Reader reader = new InputStreamReader(emptyBytecountStream,
                encoding);
        int r1, r2;
        int charSkipped = 0;
        boolean foundHeader = false;

        // This is the check to skip the initial few bytes

        while ((r1 = reader.read()) != -1 && (r2 = reader.read()) != -1) {
            char ch1 = (char) r1;
            char ch2 = (char) r2;
            if (ch1 == 'P' && ch2 == 'K') {
                foundHeader = true;
                break;
            }
            charSkipped += 2;
        }
        emptyBytecountStream.close();

        zipStarterStream = new FileInputStream(filePath);
        zis = new ZipInputStream(new BufferedInputStream(zipStarterStream));

        if (foundHeader && charSkipped > 0) {
            zipStarterStream.skip(charSkipped);
        }

        String outputPath = getPublicStorageDir("")
                + "/"
                + filePath.substring(filePath.lastIndexOf("/") + 1,
                        filePath.length());

        new File(outputPath).mkdir();
        ZipEntry entry;

        while ((entry = zis.getNextEntry()) != null) {

            String currentfileName = entry.getName();
            File destFile = new File(outputPath, currentfileName);
            File destinationParent = destFile.getParentFile();

            destinationParent.mkdirs();

            if (!entry.isDirectory()) {
                int currentByte;
                byte data[] = new byte[BUFFER];

                // write the current file to disk
                FileOutputStream fos = new FileOutputStream(destFile);
                BufferedOutputStream dest = new BufferedOutputStream(fos,
                        BUFFER);

                // read and write until last byte is encountered
                while ((currentByte = zis.read(data, 0, BUFFER)) != -1) {
                    dest.write(data, 0, currentByte);
                }
                dest.flush();
                dest.close();
            }

            if (currentfileName.endsWith(".zip")) {
                extractZipFolder(destFile.getAbsolutePath());
            }
        }
        zis.close();
    } catch (IOException e) {
        e.printStackTrace();

    }
于 2012-12-10T01:21:58.153 に答える
0

正確な例外メッセージは何ですか?

ZIP ファイルにはフォーマットの違いがある場合があることに注意してください。例: 暗号化を使用しましたか? これは、組み込みの Java ルーチンの問題です。

そして: 別の ZIP ツールで再圧縮を試みましたか?

于 2012-12-09T19:44:20.623 に答える