简体   繁体   English

使用java提取.rar文件

[英]Using java to extract .rar files

I am looking a ways to unzip .rar files using Java and where ever I search i keep ending up with the same tool - JavaUnRar .我正在寻找一种使用 Java 解压缩.rar文件的方法,无论我在哪里搜索,我都会以相同的工具 - JavaUnRar I have been looking into unzipping .rar files with this but all the ways i seem to find to do this are very long and awkward like in this example我一直在研究用这个解压.rar文件,但我似乎找到的所有方法都非常冗长和笨拙,就像这个例子一样

I am currently able to extract .tar , .tar.gz , .zip and .jar files in 20 lines of code or less so there must be a simpler way to extract .rar files, does anybody know?我目前能够在 20 行或更少的代码中提取.tar.tar.gz.zip.jar文件,所以必须有更简单的方法来提取.rar文件,有人知道吗?

Just if it helps anybody this is the code that I am using to extract both .zip and .jar files, it works for both如果它对任何人有帮助,这就是我用来提取.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();
    }
}

You are able to extract .gz , .zip , .jar files as they use number of compression algorithms built into the Java SDK.您可以提取.gz.zip.jar文件,因为它们使用了 Java SDK 内置的多种压缩算法。

The case with RAR format is a bit different. RAR格式的情况有点不同。 RAR is a proprietary archive file format. RAR 是专有的存档文件格式。 RAR license does not allow to include it into software development tools like Java SDK. RAR 许可证不允许将其包含到 Java SDK 等软件开发工具中。

The best way to unrar your files will be using 3rd party libraries such as junrar .解压缩文件的最佳方法是使用 3rd 方库,例如 junrar

You can find some references to other Java RAR libraries in SO question RAR archives with java .您可以在 SO question RAR archives with java中找到对其他 Java RAR 库的一些引用。 Also SO question How to compress text file to rar format using java program explains more on different workarounds (eg using Runtime ).还有一个问题How to compress text file to rar format using java program解释了更多不同的解决方法(例如使用Runtime )。

You can use the library junrar你可以使用库junrar

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

Code example:代码示例:

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

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

In addition to supporting a large number of archive formats, version 16.02-2.01 has full support for RAR5 extraction with:除了支持大量存档格式外,16.02-2.01 版还全面支持 RAR5 提取:

  • password protected archives密码保护档案
  • archives with encrypted headers带有加密标题的存档
  • archives splitted in volumes档案分成几卷

gradle摇篮

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

or maven或行家

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

And code example和代码示例


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 Happy 40th birthday to you. PS @BorisBrodski https://github.com/borisbrodski祝你 40 岁生日快乐。 Hope you had a great celebration.希望你有一个伟大的庆祝活动。 Thanks for your work!感谢您的工作!

you could simply add this maven dependency to you code:您可以简单地将此 Maven 依赖项添加到您的代码中:

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

and then use this code for extract rar file:然后使用此代码提取 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.");

This method helps to extract files to streams from rar(RAR5) file stream if you have input stream.如果您有输入流,此方法有助于将文件从 rar(RAR5) 文件流中提取到流中。 In my case I was processing MimeBodyPart from email.在我的例子中,我正在处理来自电子邮件的 MimeBodyPart。

The example from @Alexey Bril didn't work for me.来自@Alexey Bril 的示例对我不起作用。

Dependencies are the same依赖是一样的

Gradle摇篮

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

Maven行家

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

Code代码

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