簡體   English   中英

使用java提取.rar文件

[英]Using java to extract .rar files

我正在尋找一種使用 Java 解壓縮.rar文件的方法,無論我在哪里搜索,我都會以相同的工具 - JavaUnRar 我一直在研究用這個解壓.rar文件,但我似乎找到的所有方法都非常冗長和笨拙,就像這個例子一樣

我目前能夠在 20 行或更少的代碼中提取.tar.tar.gz.zip.jar文件,所以必須有更簡單的方法來提取.rar文件,有人知道嗎?

如果它對任何人有幫助,這就是我用來提取.zip.jar文件的代碼,它適用於兩者

 public void getZipFiles(String zipFile, String destFolder) throws IOException {
    BufferedOutputStream dest = null;
    ZipInputStream zis = new ZipInputStream(
                                       new BufferedInputStream(
                                             new FileInputStream(zipFile)));
    ZipEntry entry;
    while (( entry = zis.getNextEntry() ) != null) {
        System.out.println( "Extracting: " + entry.getName() );
        int count;
        byte data[] = new byte[BUFFER];

        if (entry.isDirectory()) {
            new File( destFolder + "/" + entry.getName() ).mkdirs();
            continue;
        } else {
            int di = entry.getName().lastIndexOf( '/' );
            if (di != -1) {
                new File( destFolder + "/" + entry.getName()
                                             .substring( 0, di ) ).mkdirs();
            }
        }
        FileOutputStream fos = new FileOutputStream( destFolder + "/"
                                                     + entry.getName() );
        dest = new BufferedOutputStream( fos );
        while (( count = zis.read( data ) ) != -1) 
            dest.write( data, 0, count );
        dest.flush();
        dest.close();
    }
}

您可以提取.gz.zip.jar文件,因為它們使用了 Java SDK 內置的多種壓縮算法。

RAR格式的情況有點不同。 RAR 是專有的存檔文件格式。 RAR 許可證不允許將其包含到 Java SDK 等軟件開發工具中。

解壓縮文件的最佳方法是使用 3rd 方庫,例如 junrar

您可以在 SO question RAR archives with java中找到對其他 Java RAR 庫的一些引用。 還有一個問題How to compress text file to rar format using java program解釋了更多不同的解決方法(例如使用Runtime )。

你可以使用庫junrar

<dependency>
   <groupId>com.github.junrar</groupId>
   <artifactId>junrar</artifactId>
   <version>0.7</version>
</dependency>

代碼示例:

            File f = new File(filename);
            Archive archive = new Archive(f);
            archive.getMainHeader().print();
            FileHeader fh = archive.nextFileHeader();
            while(fh!=null){        
                    File fileEntry = new File(fh.getFileNameString().trim());
                    System.out.println(fileEntry.getAbsolutePath());
                    FileOutputStream os = new FileOutputStream(fileEntry);
                    archive.extractFile(fh, os);
                    os.close();
                    fh=archive.nextFileHeader();
            }

你可以使用http://sevenzipjbind.sourceforge.net/index.html

除了支持大量存檔格式外,16.02-2.01 版還全面支持 RAR5 提取:

  • 密碼保護檔案
  • 帶有加密標題的存檔
  • 檔案分成幾卷

搖籃

implementation 'net.sf.sevenzipjbinding:sevenzipjbinding:16.02-2.01'
implementation 'net.sf.sevenzipjbinding:sevenzipjbinding-all-platforms:16.02-2.01'

或行家

<dependency>
    <groupId>net.sf.sevenzipjbinding</groupId>
    <artifactId>sevenzipjbinding</artifactId>
    <version>16.02-2.01</version>
</dependency>
<dependency>
    <groupId>net.sf.sevenzipjbinding</groupId>
    <artifactId>sevenzipjbinding-all-platforms</artifactId>
    <version>16.02-2.01</version>
</dependency>

和代碼示例


import net.sf.sevenzipjbinding.ExtractOperationResult;
import net.sf.sevenzipjbinding.IInArchive;
import net.sf.sevenzipjbinding.SevenZip;
import net.sf.sevenzipjbinding.impl.RandomAccessFileInStream;
import net.sf.sevenzipjbinding.simple.ISimpleInArchiveItem;

import java.io.*;
import java.util.HashMap;
import java.util.Map;

/**
 * Responsible for unpacking archives with the RAR extension.
 * Support Rar4, Rar4 with password, Rar5, Rar5 with password.
 * Determines the type of archive itself.
 */
public class RarExtractor {

    /**
     * Extracts files from archive. Archive can be encrypted with password
     *
     * @param filePath path to .rar file
     * @param password string password for archive
     * @return map of extracted file with file name
     * @throws IOException
     */
    public Map<InputStream, String> extract(String filePath, String password) throws IOException {
        Map<InputStream, String> extractedMap = new HashMap<>();

        RandomAccessFile randomAccessFile = new RandomAccessFile(filePath, "r");
        RandomAccessFileInStream randomAccessFileStream = new RandomAccessFileInStream(randomAccessFile);
        IInArchive inArchive = SevenZip.openInArchive(null, randomAccessFileStream);

        for (ISimpleInArchiveItem item : inArchive.getSimpleInterface().getArchiveItems()) {
            if (!item.isFolder()) {
                ExtractOperationResult result = item.extractSlow(data -> {
                    extractedMap.put(new BufferedInputStream(new ByteArrayInputStream(data)), item.getPath());

                    return data.length;
                }, password);

                if (result != ExtractOperationResult.OK) {
                    throw new RuntimeException(
                            String.format("Error extracting archive. Extracting error: %s", result));
                }
            }
        }

        return extractedMap;
    }
}

PS @BorisBrodski https://github.com/borisbrodski祝你 40 歲生日快樂。 希望你有一個偉大的慶祝活動。 感謝您的工作!

您可以簡單地將此 Maven 依賴項添加到您的代碼中:

<dependency>
    <groupId>com.github.junrar</groupId>
    <artifactId>junrar</artifactId>
    <version>0.7</version>
</dependency>

然后使用此代碼提取 rar 文件:

        File rar = new File("path_to_rar_file.rar");
    File tmpDir = File.createTempFile("bip.",".unrar");
    if(!(tmpDir.delete())){
        throw new IOException("Could not delete temp file: " + tmpDir.getAbsolutePath());
    }
    if(!(tmpDir.mkdir())){
        throw new IOException("Could not create temp directory: " + tmpDir.getAbsolutePath());
    }
    System.out.println("tmpDir="+tmpDir.getAbsolutePath());
    ExtractArchive extractArchive = new ExtractArchive();
    extractArchive.extractArchive(rar, tmpDir);
    System.out.println("finished.");

如果您有輸入流,此方法有助於將文件從 rar(RAR5) 文件流中提取到流中。 在我的例子中,我正在處理來自電子郵件的 MimeBodyPart。

來自@Alexey Bril 的示例對我不起作用。

依賴是一樣的

搖籃

implementation 'net.sf.sevenzipjbinding:sevenzipjbinding:16.02-2.01'
implementation 'net.sf.sevenzipjbinding:sevenzipjbinding-all-platforms:16.02-2.01'

行家

<dependency>
    <groupId>net.sf.sevenzipjbinding</groupId>
    <artifactId>sevenzipjbinding</artifactId>
    <version>16.02-2.01</version>
</dependency>
<dependency>
    <groupId>net.sf.sevenzipjbinding</groupId>
    <artifactId>sevenzipjbinding-all-platforms</artifactId>
    <version>16.02-2.01</version>
</dependency>  

代碼

private List<InputStream> getInputStreamsFromRar5InputStream(InputStream is) throws IOException {

    List<InputStream> inputStreams = new ArrayList<>();
    
    File tempFile = File.createTempFile("tempRarArchive-", ".rar", null);

    try (FileOutputStream fos = new FileOutputStream(tempFile)) {
        fos.write(is.readAllBytes());
        fos.flush();
        try (RandomAccessFile raf = new RandomAccessFile(tempFile, "r")) {// open for reading
            try (IInArchive inArchive = SevenZip.openInArchive(null, // autodetect archive type
                    new RandomAccessFileInStream(raf))) {
                // Getting simple interface of the archive inArchive
                ISimpleInArchive simpleInArchive = inArchive.getSimpleInterface();

                for (ISimpleInArchiveItem item : simpleInArchive.getArchiveItems()) {
                    if (!item.isFolder()) {
                        ExtractOperationResult result;
                        final InputStream[] IS = new InputStream[1];

                        final Integer[] sizeArray = new Integer[1];
                        result = item.extractSlow(new ISequentialOutStream() {
                            /**
                             * @param bytes of extracted data
                             * @return size of extracted data
                             */
                            @Override
                            public int write(byte[] bytes) {
                                InputStream is = new ByteArrayInputStream(bytes);
                                sizeArray[0] = bytes.length;
                                IS[0] = new BufferedInputStream(is); // Data to write to file
                                return sizeArray[0];
                            }
                        });

                        if (result == ExtractOperationResult.OK) {
                            inputStreams.add(IS[0]);
                        } else {
                            log.error("Error extracting item: " + result);
                        }
                    }
                }
            }
        }
        
    } finally {
        tempFile.delete();
    }

    return inputStreams;

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM