`
kerry001
  • 浏览: 38329 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

unrar/Archive.java

    博客分类:
  • jsp
阅读更多
/*
 * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
 * Original author: Edmund Wagner
 * Creation date: 22.05.2007
 *
 * Source: $HeadURL$
 * Last changed: $LastChangedDate$
 *
 * the unrar licence applies to all junrar source and binary distributions
 * you are not allowed to use this source to re-create the RAR compression
 * algorithm
 *
 * Here some html entities which can be used for escaping javadoc tags:
 * "&":  "&" or "&"
 * "<":  "&#060;" or "&lt;"
 * ">":  "&#062;" or "&gt;"
 * "@":  "&#064;"
 */
package de.innosystec.unrar;

import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import de.innosystec.unrar.exception.RarException;
import de.innosystec.unrar.exception.RarException.RarExceptionType;
import de.innosystec.unrar.io.IReadOnlyAccess;
import de.innosystec.unrar.io.ReadOnlyAccessFile;
import de.innosystec.unrar.rarfile.AVHeader;
import de.innosystec.unrar.rarfile.BaseBlock;
import de.innosystec.unrar.rarfile.BlockHeader;
import de.innosystec.unrar.rarfile.CommentHeader;
import de.innosystec.unrar.rarfile.EAHeader;
import de.innosystec.unrar.rarfile.EndArcHeader;
import de.innosystec.unrar.rarfile.FileHeader;
import de.innosystec.unrar.rarfile.MacInfoHeader;
import de.innosystec.unrar.rarfile.MainHeader;
import de.innosystec.unrar.rarfile.MarkHeader;
import de.innosystec.unrar.rarfile.ProtectHeader;
import de.innosystec.unrar.rarfile.SignHeader;
import de.innosystec.unrar.rarfile.SubBlockHeader;
import de.innosystec.unrar.rarfile.UnixOwnersHeader;
import de.innosystec.unrar.rarfile.UnrarHeadertype;
import de.innosystec.unrar.unpack.ComprDataIO;
import de.innosystec.unrar.unpack.Unpack;

/**
 * DOCUMENT ME
 *
 * @author $LastChangedBy$
 * @version $LastChangedRevision$
 */
public class Archive implements Closeable {
    
    private static Logger logger = Logger.getLogger(Archive.class.getName());

    private File file;

    private IReadOnlyAccess rof;

    private final UnrarCallback unrarCallback;

    private final ComprDataIO dataIO;

    private final List<BaseBlock> headers = new ArrayList<BaseBlock>();

    private MarkHeader markHead = null;

    private MainHeader newMhd = null;
    
    private EndArcHeader endHeader = null;
    
    private Unpack unpack;

    /** Archive data CRC. */
    private long arcDataCRC = 0xffffffff;

    private int currentHeaderIndex;

    private boolean encrypted = false;

    private int sfxSize = 0;

    /** Size of packed data in current file. */
    private long totalPackedSize = 0L;

    /** Number of bytes of compressed data read from current file. */
    private long totalPackedRead = 0L;

    public Archive(File file) throws RarException, IOException {
        this(file, null);
    }

    /**
     * create a new archive object using the given file
     * @param file the file to extract
     * @throws RarException
     */
    public Archive(File file, UnrarCallback unrarCallback)
            throws RarException, IOException {
        setFile(file);
        this.unrarCallback = unrarCallback;
        dataIO = new ComprDataIO(this);
    }

    public File getFile() {
        return file;
    }

    void setFile(File file) throws IOException {
        this.file = file;
        totalPackedSize = 0L;
        totalPackedRead = 0L;
        close();
        rof = new ReadOnlyAccessFile(file);
        try {
            readHeaders();
        }
        catch (Exception e) {
            logger.log(Level.WARNING,
                    "exception in archive constructor maybe file is encrypted " +
                    "or currupt", e);
            //ignore exceptions to allow exraction of working files in
            //corrupt archive
        }
        // Calculate size of packed data
        for (BaseBlock block : headers) {
            if (block.getHeaderType() == UnrarHeadertype.FileHeader) {
                totalPackedSize += ((FileHeader)block).getFullPackSize();
            }
        }
        if (unrarCallback != null) {
            unrarCallback.volumeProgressChanged(totalPackedRead,
                    totalPackedSize);
        }
    }

    public void bytesReadRead(int count) {
        if (count > 0) {
            totalPackedRead += count;
            if (unrarCallback != null) {
                unrarCallback.volumeProgressChanged(totalPackedRead,
                        totalPackedSize);
            }
        }
    }

    public IReadOnlyAccess getRof() {
        return rof;
    }
    
    /**
	 * @return returns all file headers of the archive
	 */
	public List<FileHeader> getFileHeaders(){
		List<FileHeader> list = new ArrayList<FileHeader>();
		for (BaseBlock block: headers) {
			if(block.getHeaderType().equals(UnrarHeadertype.FileHeader)){
				list.add((FileHeader)block);
			}
		}
		return list;
	}
    
    public FileHeader nextFileHeader() {
        int n = headers.size();
        while (currentHeaderIndex < n) {
            BaseBlock block = headers.get(currentHeaderIndex++);
            if (block.getHeaderType() == UnrarHeadertype.FileHeader) {
                return (FileHeader)block;
            }
        }
        return null;
    }

    public UnrarCallback getUnrarCallback() {
        return unrarCallback;
    }

    /**
     *
     * @return whether the archive is encrypted
     */
    public boolean isEncrypted() {
        if(newMhd!=null){
            return newMhd.isEncrypted();
        }else{
            throw new NullPointerException("mainheader is null");
        }
    }
    
    /**
     * Read the headers of the archive
     * @throws RarException
     */
    private void readHeaders() throws IOException, RarException{
        markHead = null;
        newMhd = null;
        endHeader = null;
        headers.clear();
        currentHeaderIndex = 0;
        int toRead = 0;
        
        long fileLength = this.file.length();

        while(true){
            int size = 0;
            long newpos = 0;
            byte[] baseBlockBuffer =new byte[BaseBlock.BaseBlockSize];
            
            long position = rof.getPosition();
            
            // Weird, but is trying to read beyond the end of the file
            if (position >= fileLength) {
            	break;
            }
            
//            logger.info("\n--------reading header--------");
            size = rof.readFully(baseBlockBuffer, BaseBlock.BaseBlockSize);
            if (size == 0){
                break;
            }
            BaseBlock block = new BaseBlock(baseBlockBuffer);
            
            block.setPositionInFile(position);
            
            
            switch(block.getHeaderType()) {
                
                case MarkHeader:
                    markHead = new MarkHeader(block);
                    if (!markHead.isSignature()) {
                        throw new RarException(
                                RarException.RarExceptionType.badRarArchive);
                    }
                    headers.add(markHead);
//                    markHead.print();
                    break;
                    
                case MainHeader:
                    int mainHeaderSize = 0;
                    toRead = block.hasEncryptVersion() ?
                            MainHeader.mainHeaderSizeWithEnc :
                            MainHeader.mainHeaderSize;
                    byte[] mainbuff = new byte[toRead];
                    mainHeaderSize = rof.readFully(mainbuff, toRead);
                    MainHeader mainhead =new MainHeader(block,mainbuff);
                    headers.add(mainhead);
                    this.newMhd = mainhead;
                    if(newMhd.isEncrypted()){
                        throw new RarException(
                                RarExceptionType.rarEncryptedException);
                    }
//                    mainhead.print();
                    break;
                    
                case SignHeader:
                    int signHeaderSize = 0;
                    toRead = SignHeader.signHeaderSize;
                    byte[] signBuff = new byte[toRead];
                    signHeaderSize = rof.readFully(signBuff, toRead);
                    SignHeader signHead = new SignHeader(block,signBuff);
                    headers.add(signHead);
//                    logger.info("HeaderType: SignHeader");
                    
                    break;
                    
                case AvHeader:
                    int avHeaderSize = 0;
                    toRead = AVHeader.avHeaderSize;
                    byte[] avBuff = new byte[toRead];
                    avHeaderSize = rof.readFully(avBuff, toRead);
                    AVHeader avHead = new AVHeader(block,avBuff);
                    headers.add(avHead);
//                    logger.info("headertype: AVHeader");
                    break;
                    
                case CommHeader:
                    int commHeaderSize = 0;
                    toRead = CommentHeader.commentHeaderSize;
                    byte[] commBuff = new byte[toRead];
                    commHeaderSize = rof.readFully(commBuff, toRead);
                    CommentHeader commHead = new CommentHeader(block,commBuff);
                    headers.add(commHead);
//                    logger.info("method: "+commHead.getUnpMethod()+"; 0x"+
//                            Integer.toHexString(commHead.getUnpMethod()));
                    newpos = commHead.getPositionInFile() +
                            commHead.getHeaderSize();
                    rof.setPosition(newpos);
                    
                    break;
                case EndArcHeader:
                    
                    toRead = 0;
                    if (block.hasArchiveDataCRC()) {
                        toRead += EndArcHeader.endArcArchiveDataCrcSize;
                    }
                    if (block.hasVolumeNumber()) {
                        toRead += EndArcHeader.endArcVolumeNumberSize;
                    }
                    EndArcHeader endArcHead;
                    if(toRead > 0){
                        int endArcHeaderSize = 0;
                        byte[] endArchBuff = new byte[toRead];
                        endArcHeaderSize = rof.readFully(endArchBuff, toRead);
                        endArcHead = new EndArcHeader(block,endArchBuff);
//                        logger.info("HeaderType: endarch\ndatacrc:"+
//                                endArcHead.getArchiveDataCRC());
                    }else{
//                        logger.info("HeaderType: endarch - no Data");
                        endArcHead = new EndArcHeader(block,null);
                    }
                    headers.add(endArcHead);
                    this.endHeader = endArcHead;
//                    logger.info("\n--------end header--------");
                    return;
                    
                default:
                    byte[] blockHeaderBuffer =
                            new byte[BlockHeader.blockHeaderSize];
                    int bhsize = rof.readFully(blockHeaderBuffer,
                            BlockHeader.blockHeaderSize);
                    BlockHeader blockHead = new BlockHeader(block,
                            blockHeaderBuffer);
                    
                    switch(blockHead.getHeaderType()) {
                        case NewSubHeader:
                        case FileHeader:
                            toRead = blockHead.getHeaderSize()-
                                    BlockHeader.BaseBlockSize-
                                    BlockHeader.blockHeaderSize;
                            byte[] fileHeaderBuffer = new byte[toRead];
                            int fhsize = rof.readFully(fileHeaderBuffer,
                                    toRead);
                            
                            FileHeader fh = new FileHeader(blockHead,
                                    fileHeaderBuffer);
//                            if (DEBUG) {
//                                fh.print();
//                            }
                            headers.add(fh);
                            newpos = fh.getPositionInFile() +
                                    fh.getHeaderSize() + fh.getFullPackSize();
                            rof.setPosition(newpos);
                            break;
                            
                        case ProtectHeader:
                            toRead = blockHead.getHeaderSize()-
                                    BlockHeader.BaseBlockSize-
                                    BlockHeader.blockHeaderSize;
                            byte[] protectHeaderBuffer = new byte[toRead];
                            int phsize = rof.readFully(protectHeaderBuffer,
                                    toRead);
                            ProtectHeader ph = new ProtectHeader(blockHead,
                                    protectHeaderBuffer);
                            
//                            logger.info("totalblocks"+ph.getTotalBlocks());
                            newpos = ph.getPositionInFile() +
                                    ph.getHeaderSize();
                            rof.setPosition(newpos);
                            break;
                            
                        case SubHeader:
						{
							byte[] subHeadbuffer = new byte[SubBlockHeader.SubBlockHeaderSize];
							int subheadersize = rof.readFully(subHeadbuffer, SubBlockHeader.SubBlockHeaderSize);
							SubBlockHeader subHead = new SubBlockHeader(blockHead,subHeadbuffer);
							subHead.print();
							switch (subHead.getSubType()) {
								case MAC_HEAD:
								{
									byte[] macHeaderbuffer = new byte[MacInfoHeader.MacInfoHeaderSize];
									int macheadersize = rof.readFully(macHeaderbuffer, MacInfoHeader.MacInfoHeaderSize);
									MacInfoHeader macHeader = new MacInfoHeader(subHead,macHeaderbuffer);
									macHeader.print();
									headers.add(macHeader);
									
									break;
								}
									//TODO implement other subheaders
								case BEEA_HEAD:
									break;
								case EA_HEAD:
								{
									byte[] eaHeaderBuffer = new byte[EAHeader.EAHeaderSize];
									int eaheadersize = rof.readFully(eaHeaderBuffer, EAHeader.EAHeaderSize);
									EAHeader eaHeader = new EAHeader(subHead,eaHeaderBuffer);
									eaHeader.print();
									headers.add(eaHeader);
									
									break;
								}
								case NTACL_HEAD:
									break;
								case STREAM_HEAD:
									break;
								case UO_HEAD:
									toRead = subHead.getHeaderSize();
									toRead -= BaseBlock.BaseBlockSize;
									toRead -= BlockHeader.blockHeaderSize;
									toRead -= SubBlockHeader.SubBlockHeaderSize;
									byte[] uoHeaderBuffer = new byte[toRead];
									int uoHeaderSize = rof.readFully(uoHeaderBuffer, toRead);
									UnixOwnersHeader uoHeader = new UnixOwnersHeader(subHead,uoHeaderBuffer);
									uoHeader.print();
									headers.add(uoHeader);
									break;
								default:
									break;
							}
		
							break;
						}
                        default:
                            logger.warning("Unknown Header");
                            throw new RarException(
                                    RarExceptionType.notRarArchive);
                            
                    }
            }
//            logger.info("\n--------end header--------");
        }
    }

    /**
     * Extract the file specified by the given header and write it
     * to the supplied output stream
     *
     * @param header the header to be extracted
     * @param os the outputstream
     * @throws RarException
     */
    public void extractFile(FileHeader hd, OutputStream os)
            throws RarException{
        if (!headers.contains(hd)){
            throw new RarException(RarExceptionType.headerNotInArchive);
        }
        try {
            doExtractFile(hd, os);
        }
        catch (Exception e) {
            if (e instanceof RarException){
                throw (RarException)e;
            } else{
                throw new RarException(e);
            }
        }
    }

    private void doExtractFile(FileHeader hd, OutputStream os)
            throws RarException, IOException {
        dataIO.init(os);
        dataIO.init(hd);
        dataIO.setUnpFileCRC(this.isOldFormat()?0:0xffFFffFF);
        if(unpack==null){
            unpack = new Unpack(dataIO);
        }
        if(!hd.isSolid()){
            unpack.init(null);
        }
        unpack.setDestSize(hd.getFullUnpackSize());
        try {
            unpack.doUnpack(hd.getUnpVersion(), hd.isSolid());
            // Verify file CRC
            hd = dataIO.getSubHeader();
            long actualCRC = hd.isSplitAfter() ?
                    ~dataIO.getPackedCRC() : ~dataIO.getUnpFileCRC();
            int expectedCRC = hd.getFileCRC();
            if(actualCRC != expectedCRC){
                throw new RarException(RarExceptionType.crcError);
            }
//            if (!hd.isSplitAfter()) {
//                // Verify file CRC
//                if(~dataIO.getUnpFileCRC() != hd.getFileCRC()){
//                    throw new RarException(RarExceptionType.crcError);
//                }
//            }
        }
        catch (Exception e) {
        	unpack.cleanUp();
            if (e instanceof RarException){
                //throw new RarException((RarException)e);
                throw (RarException)e;
            }
            else{
                throw new RarException(e);
            }
        }
    }
    
    /**
     * @return returns the main header of this archive
     */
    public MainHeader getMainHeader() {
        return newMhd;
    }
    
    /**
     * @return whether the archive is old format
     */
    public boolean isOldFormat() {
        return markHead.isOldFormat();
    }

    /** Close the underlying compressed file. */
    public void close() throws IOException {
        if (rof != null) {
            rof.close();
            rof = null;
        }
    }
}

URL:http://svn.atlassian.com/svn/public/atlassian/vendor/java-unrar/trunk/src/main/java/de/innosystec/unrar/Archive.java
分享到:
评论

相关推荐

    java-unrar-0.3.jar以及commons-logging-1.1.1.jar

    这里提到的"java-unrar-0.3.jar"和"commons-logging-1.1.1.jar"是两个关键的Java库,它们提供了处理RAR文件和日志管理的能力。 1. **java-unrar-0.3.jar**: 这是一个开源的Java库,允许开发者在Java程序中读取和...

    java 压缩/解压 .zip/.rar/.tar 文件

    java.util.Enumeration&lt;ZipEntry&gt; e = zipFile.getEntries(); while (e.hasMoreElements()) { ZipEntry zipEnt = e.nextElement(); // 解压缩逻辑... } ``` 对于`.zip`文件的压缩,可以使用`ZipOutputStream`,...

    java解压rar 包含java-unrar-0.3.jar

    import java.io.FileOutputStream; import java.io.IOException; public class RarExtractor { public static void main(String[] args) { try (final Archive archive = new Archive(new File("path_to_your_rar...

    java-unrar-0.3

    Java-unrar-0.3是一个基于Java的库,专门用于解压RAR文件格式。RAR是一种流行的压缩格式,由RARlab开发,通常用于在Windows环境中压缩和分发文件。然而,由于Java的跨平台特性,Java-unrar库使得在Java应用程序中...

    unRar-0.5.jar

    《Java环境下利用unRar库解压RAR文件详解》 在Java编程环境中,处理压缩文件是常见的需求之一,其中RAR格式的压缩文件由于其高效的数据压缩比和强大的特性,被广泛应用。然而,Java标准库并未内置对RAR文件的直接...

    ant.rarjava-unrar-0.5.jar一键下载

    JAR是Java Archive的缩写,它是Java平台特有的归档格式,用于打包Java类、资源和元数据,通常用于创建可执行的Java应用程序或库。 “java-unrar-0.5.jar”是这个库的具体版本号,0.5表示这是该库的一个早期版本。库...

    Java带密码解压缩RAR压缩包(内附代码)

    在这种情况下,我们可以使用`java-unrar`库,这是一个基于GNU Crypto的Java RAR工具包。文件名`java-unrar_gnu-crypto`可能就是这个库的源代码或者二进制包。 要使用`java-unrar`库,首先将其添加到你的项目依赖中...

    java-unrar-解压Winrar例子

    import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import de.innosystec.unrar.Archive; import de.innosystec.unrar.exception.RarException; import de....

    java-unrar-decryption-supported

    import java.io.FileOutputStream; import java.io.IOException; public class RarDecryptionExample { public static void main(String[] args) throws IOException, RarException { String rarFilePath = "path...

    unrar jar包

    "unrar jar包"是一种专门用于在Java中处理RAR文件的库,它允许开发者实现RAR文件的解压缩以及压缩功能。本文将深入探讨如何使用这个jar包来操作RAR文件,并介绍相关的重要知识点。 首先,`java-unrar-0.5.jar`是...

    使用jna调用unrar解压rar文件

    在提供的`jnaUnrar`工程中,可能包含了示例代码、配置文件以及所需的jar依赖,例如JNA库和unrar的Java绑定。使用Eclipse打开该工程,可以查看和学习完整的解压流程。通过运行工程,我们可以看到如何实际调用这些函数...

    java unrar src&jar

    import java.io.IOException; public class UnrarExample { public static void main(String[] args) { try (Archive archive = new Archive(new File("path_to_your_rar_file.rar"))) { for (FileHeader header...

    java操作rar文件

    Unrar.unrarFile(archive, volumes, fileHeader, new File("output_directory"), false); } ``` 创建RAR压缩文件则需要使用`com.rarlab.junrar.archive.ArchiveWriter`类。首先创建一个`ArchiveWriter`对象,然后...

    java解压jar包及示例

    1. **打开文件**:使用`java.io`包中的`FileInputStream`打开RAR文件。 2. **创建RarFile对象**:使用`com.github.junrar.Archive`类创建一个RarFile对象,该对象代表RAR文件的内容。 3. **遍历文件**:通过`Archive...

    java解压缩rar(包含源码)

    一个国外用java解压缩rar的包 代码已经被我整理过,原来基于jdk5.0以上,现在采用jdk142以上。 主操作类 de.innosystec.unrar.Archive 演示代码在其中的 main() 函数中

    java几个常用的jar包

    Java Logging API是一个用于日志记录的标准库,通常包含在`java.util.logging`包中。它提供了灵活的日志级别,如SEVERE、WARNING、INFO、CONFIG、FINE、FINER和FINEST,以及多种日志处理器和配置选项。开发者可以...

    java 解压 .rar 文件 源码 人头担保可用

    import java.io.File; entry.extractFile(new File("path/to/destination/directory/" + entry.getLocalFileNameString())); ``` 5. **处理密码保护的RAR文件**:如果RAR文件被密码保护,`RarEntry`的`extractFile...

    取压缩包中(RAR)全部文件名.rar

    - 对于Linux和Mac用户,可以使用`unrar`命令,`unrar n archive.rar`会列出文件名。 - 自动化脚本:你还可以编写批处理脚本或shell脚本来批量处理多个RAR文件。 总之,无论你是IT专业人员还是普通用户,提取RAR...

Global site tag (gtag.js) - Google Analytics