国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發(fā)設計 > 正文

跟我學制作Pak文件

2019-11-18 16:15:35
字體:
來源:轉載
供稿:網友

  版權聲明:本文可以自由轉載,轉載時請務必以超鏈接形式標明文章原始出處和作者信息及本聲明
作者:cleverpig(http://blog.matrix.org.cn/page/cleverpig)
原文:http://www.matrix.org.cn/resource/article/43/43966_J2ME_Pak.Html
關鍵字:pak,j2me,減肥


序言:

    由于前些時間,一些matrixer常問關于j2me中使用Pak文件的問題。本人雖學藝不深,但滿懷熱心的做了一番探索,現(xiàn)將制作Pak文件的看法和方法公布出來,大家多多提意見。

一、什么是Pak文件:

    Pak文件就是將多個文件打包為一個單獨文件,在這個文件中保存著多個文件的數(shù)據,當然還有一些描述文件結構的數(shù)據。所以將“Pak”作為文件的后綴是一種常規(guī)的用法,大家可以自定義其它的文件后綴。

二、為什么使用Pak文件:

    由于MIDP對發(fā)布安裝的j2me程序大小進行了限制,所以縮小發(fā)布程序就意味著能夠提供更多的程序或者內容(如圖片、音樂)給用戶。而通過研究發(fā)現(xiàn)zip/jar算法對大文件的壓縮率高于對等量的多個小文件的壓縮率。

    當然還有其它方法,這里簡單做一下討論比如使用混淆器PRoGuard的“-overloadaggressively”選項使jar文件縮小,但也會導致一些錯誤,因為這種方法生成jar中的class符合java byte code標準,但是與java語法相悖,嚴重的可能造成一些jre對Object的序列化錯誤。

    所以使用Pak方法將程序中要用到的資源(圖片、音樂、文本)組合為單一文件是一個安全有效的方法。而且對于一些商用程序,完全可以在pak文件中對文件數(shù)據進行加密,很好的保護了作者和公司的權益。本人的sample中使用了簡單的“加減法”加密,對于手機這類設備來講是一個效率較高的選擇。

三、Pak文件的結構:

    大家可以自己設計Pak文件結構,本人這里只是拋磚引玉的作個sample。下面就是本人設計的Pak文件結構:

PAK File Header:Pak文件的頭部


  * 簽名:6字節(jié)char數(shù)組
* 版本號:32位float
* 文件table數(shù)量:32位整數(shù)
* 密碼行為:8位字節(jié)
* 密碼:8位字節(jié)
* 文件唯一ID:10字節(jié)char數(shù)組
* 保留位:32位整數(shù)(4字節(jié))


File Table:Pak文件中包含文件的列表,在一個Pak文件中一個被包含的文件對應一個File Table。


* 文件名:30字節(jié)char數(shù)組
* 文件大小:32位整型
* 文件在pak文件中的位移:32位整數(shù)


Concatenated File Data:按File Table的順序連接在一起的文件數(shù)據。

* 文件數(shù)據


四、程序框架:
    
    說明:由于Pak文件的制作和使用分別要使用兩個java應用領域:j2se和j2me,所以本人將PakUtil類制作了2個版本(j2se和j2me)。

    程序框架如下:
    1。PakHeader類,定義了Pak文件頭。
    2。PakFileTable類,定義Pak文件table。
    3。PakUtil類(j2se版),具備兩個功能:將多個png圖片合成一個Pak文件,并使用簡單的加減加密法對其進行加密;從Pak文件中取出png圖片,構造byte數(shù)組(可以用來構造Image對象)或者寫為文件。
       PakUtil類(j2me版),具備的功能:從Pak文件中取出png圖片,構造byte數(shù)組(可以用來構造Image對象)。

五、PakHeader和PakFileTable類:
    
PakHeader.java:

package cn.org.matrix.gmatrix.gameLab.util.pak;

/**
* Pak文件頭:
* 結構:
*   簽名:6字節(jié)char數(shù)組
*   版本號:32位float
*   文件table數(shù)量:32位整數(shù)
*   密碼行為:8位字節(jié)
*   密碼:8位字節(jié)
*   文件唯一ID:10字節(jié)char數(shù)組
*   保留位:32位整數(shù)(4字節(jié))
* @author cleverpig
*
*/
class PakHeader {
        //定義文件唯一ID長度
        public static final int UNIQUEID_LENGTH=10;
        //定義文件簽名長度
        public static final int SIGNATURE_LENGTH=6;
        //定義加法運算
        public static final int ADDITION_CIPHERACTION=0;
        //定義減法運算
        public static final int SUBTRACT_CIHOERACTION=1;
        //文件簽名
        private char[] signature=new char[SIGNATURE_LENGTH];
        //版本號
        private float version=0f;
        //文件table數(shù)量
        private long numFileTableEntries=0;
        //密碼使用方法:在原數(shù)據上進行加法還是減法
        private byte cipherAction=ADDITION_CIPHERACTION;
        //密碼值
        private byte cipherValue=0x00;
        //唯一ID
        private char[] uniqueID=new char[UNIQUEID_LENGTH];
        //保留的4字節(jié)
        private long reserved=0;
        
        public PakHeader(){        
        }
        
        /**
         * 構造方法
         * @param signature 簽名
         * @param version 版本
         * @param numFileTableEntries 文件table數(shù)量
         * @param cipherAction 密碼使用方法
         * @param cipherValue 密碼值
         * @param uniqueID 唯一ID
         * @param reserved 保留的2字節(jié)
         */
        public PakHeader(char[] signature,float version,
                        long numFileTableEntries,byte cipherAction,
                        byte cipherValue,char[] uniqueID,long reserved){
                for(int i=0;i<SIGNATURE_LENGTH;this.signature[i]=signature[i],i++)
                        ;
                this.version=version;
                this.cipherAction=cipherAction;
                this.numFileTableEntries=numFileTableEntries;
                this.cipherValue=cipherValue;
                for(int i=0;i<UNIQUEID_LENGTH;this.uniqueID[i]=uniqueID[i],i++)
                        ;
                
                this.reserved=reserved;
        }
        
        public byte getCipherValue() {
                return cipherValue;
        }
        public void setCipherValue(byte cipherValue) {
                this.cipherValue = cipherValue;
        }
        public long getNumFileTableEntries() {
                return numFileTableEntries;
        }
        public void setNumFileTableEntries(long numFileTableEntries) {
                this.numFileTableEntries = numFileTableEntries;
        }
        public long getReserved() {
                return reserved;
        }
        public void setReserved(long reserved) {
                this.reserved = reserved;
        }
        public char[] getUniqueID() {
                return uniqueID;
        }
        public void setUniqueID(char[] uniqueID) {
                for(int i=0;i<UNIQUEID_LENGTH;this.uniqueID[i]=uniqueID[i],i++)
                        ;
        }
        public float getVersion() {
                return version;
        }
        public void setVersion(float version) {
                this.version = version;
        }
        public byte getCipherAction() {
                return cipherAction;
        }

        public void setCipherAction(byte cipherAction) {
                this.cipherAction = cipherAction;
        }

        public char[] getSignature() {
                return signature;
        }

        public void setSignature(char[] signature) {
                for(int i=0;i<SIGNATURE_LENGTH;this.signature[i] = signature[i],i++)
                        ;
        }
        
        /**
         * 返回PakHeader的大小
         * @return 返回PakHeader的大小
         */
        public static int size(){
                return SIGNATURE_LENGTH+4+4+1+1+UNIQUEID_LENGTH+4;
        }
        
        public String toString(){
                String result="";
                result+="/t簽名:"+new String(this.signature).trim()
                        +"/t版本號:"+this.version
                        +"/t文件table數(shù)量:"+this.numFileTableEntries
                        +"/t密碼行為:" +this.cipherAction
                        +"/t密碼:"+this.cipherValue
                        +"/t文件唯一ID:"+new String(this.uniqueID).trim()
                        +"/t保留位:"+this.reserved;
                return result;
        }

}


PakFileTable.java

package cn.org.matrix.gmatrix.gameLab.util.pak;

/**
* Pak文件table類
* 文件table結構:
*         文件名:30字節(jié)char數(shù)組
*         文件大小:32位整型
*         文件在pak文件中的位移:32位整數(shù)
* @author cleverpig
*
*/
class PakFileTable {
        public static final int FILENAME_LENGTH=30;
        //文件名
        private char[] fileName=new char[FILENAME_LENGTH];
        //文件大小
        private long fileSize=0L;
        //文件在pak文件中的位移
        private long offSet=0L;
        
        public PakFileTable(){
        }
        
        /**
         * 構造方法
         * @param fileName 文件名
         * @param fileSize 文件大小
         * @param offSet 文件在Pak文件中的位移
         */
        public PakFileTable(char[] fileName,
                        long fileSize,long offSet){
                for(int i=0;i<FILENAME_LENGTH;this.fileName[i]=fileName[i],i++)
                        ;
                this.fileSize=fileSize;
                this.offSet=offSet;
        }
        
        public char[] getFileName() {
                return fileName;
        }
        public void setFileName(char[] fileName) {
                for(int i=0;i<fileName.length;this.fileName[i]=fileName[i],i++)
                        ;
        }
        public long getFileSize() {
                return fileSize;
        }
        public void setFileSize(long fileSize) {
                this.fileSize = fileSize;
        }
        public long getOffSet() {
                return offSet;
        }
        public void setOffSet(long offSet) {
                this.offSet = offSet;
        }
        /**
         * 返回文件Table的大小
         * @return 返回文件Table的大小
         */
        public static int size(){
                return FILENAME_LENGTH+4+4;
        }
        
        public String toString(){
                return "/t文件名:"+new String(this.fileName).trim()
                        +"/t文件大小:"+this.fileSize
                        +"/t文件位移:"+this.offSet;
        }
}


六、PakUtil類(j2se版):

PakUtil.java

package cn.org.matrix.gmatrix.gameLab.util.pak;

import java.io.*;
import java.util.Vector;
/**
* Pak工具類
* 功能:
* 1.將多個png圖片合成一個Pak文件,并使用簡單的加減加密法對其進行加密;
* 2.從Pak文件中取出png圖片,構造byte數(shù)組(可以用來構造Image對象)或者寫為文件
* @author cleverpig
*
*/
public class PakUtil {

        public PakUtil(){
        }
        
        /**
         * 返回文件長度
         * @param filePath 文件路徑
         * @return 文件長度
         */
        private long getFileSize(String filePath){
                File file=new File(filePath);
                return file.length();
        }
        
        /**
         * 返回文件名
         * @param filePath 文件路徑
         * @return 文件名
         */
        private String getFileName(String filePath){
                File file=new File(filePath);
                return file.getName();
        }
        
        /**
         * 計算文件位移的起始點
         * @return 文件位移的起始點
         */
        private long workOutOffsetStart(PakHeader header){
                //計算出文件頭+文件table的長度
                return PakHeader.size()+header.getNumFileTableEntries()*PakFileTable.size();
        }
        
        /**
         * 計算文件位移
         * @param fileIndex 文件序號
         * @param lastFileOffset 上一個文件位移
         * @return  文件在pak文件中的位移
         */
        private long workOutNextOffset(long sourceFileSize,long lastFileOffset){
                return lastFileOffset+sourceFileSize;
        }
        
        /**
         * 生成文件table
         * @param sourceFileName 源文件名
         * @param sourceFileSize 源文件長度
         * @param currentFileOffset 當前文件位移
         * @return 生成的PakFileTable對象
         */
        private PakFileTable generateFileTable(String sourceFileName,
                        long sourceFileSize,long currentFileOffset){
                PakFileTable ft=new PakFileTable();
                ft.setFileName(sourceFileName.toCharArray());
                ft.setFileSize(sourceFileSize);
                ft.setOffSet(currentFileOffset);
                return ft;
        }
        
        /**
         * 將char字符數(shù)組寫入到DataOutputStream中
         * @param toWriteCharArray 被寫入的char數(shù)組
         * @param dos DataOutputStream
         * @throws Exception
         */
        private void writeCharArray(char[] toWriteCharArray,DataOutputStream dos) throws Exception{
                for(int i=0;i<toWriteCharArray.length;dos.writeChar(toWriteCharArray[i]),i++);
        }
        
        /**
         * 使用文件頭中的密碼對數(shù)據進行加密
         * @param buff 被加密的數(shù)據
         * @param buffLength 數(shù)據的長度
         * @param header 文件頭
         */
        private void encryptBuff(byte[] buff,int buffLength,PakHeader header){
                for(int i=0;i<buffLength;i++){
                        switch(header.getCipherAction()){
                        case PakHeader.ADDITION_CIPHERACTION:
                                buff[i]+=header.getCipherValue();
                                break;
                        case PakHeader.SUBTRACT_CIHOERACTION:
                                buff[i]-=header.getCipherValue();
                                break;
                        }
                }
        }
        
        /**
         * 使用文件頭中的密碼對數(shù)據進行解密
         * @param buff 被解密的數(shù)據
         * @param buffLength 數(shù)據的長度
         * @param header 文件頭
         */
        private void decryptBuff(byte[] buff,int buffLength,PakHeader header){
                for(int i=0;i<buffLength;i++){
                        switch(header.getCipherAction()){
                        case PakHeader.ADDITION_CIPHERACTION:
                                buff[i]-=header.getCipherValue();
                                break;
                        case PakHeader.SUBTRACT_CIHOERACTION:
                                buff[i]+=header.getCipherValue();
                                break;
                        }
                }
        }
        
        /**
         * 制作Pak文件
         * @param sourceFilePath 源文件路徑數(shù)組
         * @param destinateFilePath 目的文件路徑(Pak文件)
         * @param cipherAction 密碼行為
         * @param cipherValue 密碼
         * @throws Exception
         */
        public void makePakFile(String[] sourceFilePath,
                        String destinateFilePath,PakHeader header) throws Exception{
                
                PakFileTable[] fileTable=new PakFileTable[sourceFilePath.length];
                //計算文件位移起始點
                long fileOffset=workOutOffsetStart(header);
                //逐個建立文件table
                for(int i=0;i<sourceFilePath.length;i++){
                        String sourceFileName=getFileName(sourceFilePath[i]);
                        long sourceFileSize=getFileSize(sourceFilePath[i]);
                        PakFileTable ft=generateFileTable(sourceFileName,sourceFileSize,fileOffset);
                        //計算下一個文件位移
                        fileOffset=workOutNextOffset(sourceFileSize,fileOffset);
                        fileTable[i]=ft;
                }
                //寫入文件頭
                File wFile=new File(destinateFilePath);
                FileOutputStream fos=new FileOutputStream(wFile);
                DataOutputStream dos=new DataOutputStream(fos);
                writeCharArray(header.getSignature(),dos);
                dos.writeFloat(header.getVersion());
                dos.writeLong(header.getNumFileTableEntries());
                dos.writeByte(header.getCipherAction());
                dos.writeByte(header.getCipherValue());
                writeCharArray(header.getUniqueID(),dos);
                dos.writeLong(header.getReserved());
                //寫入文件table
                for(int i=0;i<fileTable.length;i++){
                        writeCharArray(fileTable[i].getFileName(),dos);
                        dos.writeLong(fileTable[i].getFileSize());

                        dos.writeLong(fileTable[i].getOffSet());
                }
                //寫入文件數(shù)據
                for(int i=0;i<fileTable.length;i++){
                        File ftFile=new File(sourceFilePath[i]);
                        FileInputStream ftFis=new FileInputStream(ftFile);
                        DataInputStream ftDis=new DataInputStream(ftFis);
                        byte[] buff=new byte[256];
                        int readLength=0;
                        while((readLength=ftDis.read(buff))!=-1){
                                encryptBuff(buff,readLength,header);
                                dos.write(buff,0,readLength);
                        }
                        ftDis.close();
                        ftFis.close();
                }
                dos.close();        
        }
        
        /**
         * 從DataInputStream讀取char數(shù)組
         * @param dis DataInputStream
         * @param readLength 讀取長度
         * @return char數(shù)組
         * @throws Exception
         */
        private char[] readCharArray(DataInputStream dis,int readLength) throws Exception{
                char[] readCharArray=new char[readLength];
                
                for(int i=0;i<readLength;i++){
                        readCharArray[i]=dis.readChar();
                }
                return readCharArray;
        }
        
        /**
         * 從PAK文件中讀取文件頭
         * @param dis DataInputStream
         * @return PakHeader
         * @throws Exception
         */
        private PakHeader readHeader(DataInputStream dis) throws Exception{
                PakHeader header=new PakHeader();
                char[] signature=readCharArray(dis,PakHeader.SIGNATURE_LENGTH);
                header.setSignature(signature);
                header.setVersion(dis.readFloat());
                header.setNumFileTableEntries(dis.readLong());
                header.setCipherAction(dis.readByte());
                header.setCipherValue(dis.readByte());
                char[] uniqueID=readCharArray(dis,PakHeader.UNIQUEID_LENGTH);
                header.setUniqueID(uniqueID);
                header.setReserved(dis.readLong());
                return header;
        }
        
        /**
         * 讀取所有的文件table
         * @param dis DataInputStream
         * @param fileTableNumber 文件表總數(shù)
         * @return 文件table數(shù)組
         * @throws Exception
         */
        private PakFileTable[] readFileTable(DataInputStream dis,int fileTableNumber) throws Exception{
                PakFileTable[] fileTable=new PakFileTable[fileTableNumber];
                for(int i=0;i<fileTableNumber;i++){
                        PakFileTable ft=new PakFileTable();
                        ft.setFileName(readCharArray(dis,PakFileTable.FILENAME_LENGTH));
                        ft.setFileSize(dis.readLong());
                        ft.setOffSet(dis.readLong());
                        fileTable[i]=ft;
                }
                return fileTable;
        }
        
        /**
         * 從pak文件讀取文件到byte數(shù)組
         * @param dis DataInputStream
         * @param fileTable PakFileTable
         * @return byte數(shù)組
         * @throws Exception
         */
        private byte[] readFileFromPak(DataInputStream dis,PakHeader header,PakFileTable fileTable) throws Exception{
                dis.skip(fileTable.getOffSet()-workOutOffsetStart(header));
                //
                int fileLength=(int)fileTable.getFileSize();
                byte[] fileBuff=new byte[fileLength];
                int readLength=dis.read(fileBuff,0,fileLength);
                if (readLength<fileLength){
                        System.out.println("讀取數(shù)據長度不正確");
                        return null;
                }
                else{
                        decryptBuff(fileBuff,readLength,header);
                        return fileBuff;
                }
        }
        
        /**
         * 將buffer中的內容寫入到文件
         * @param fileBuff 保存文件內容的buffer
         * @param fileName 文件名
         * @param extractDir 文件導出目錄
         * @throws Exception
         */
        private void writeFileFromByteBuffer(byte[] fileBuff,String fileName,String extractDir) throws Exception{
                String extractFilePath=extractDir+fileName;
                File wFile=new File(extractFilePath);
                FileOutputStream fos=new FileOutputStream(wFile);
                DataOutputStream dos=new DataOutputStream(fos);
                dos.write(fileBuff);
                dos.close();
                fos.close();
        }
        
        /**
         * 從pak文件中取出指定的文件到byte數(shù)組,如果需要的話可以將byte數(shù)組寫為文件
         * @param pakFilePath  pak文件路徑
         * @param extractFileName pak文件中將要被取出的文件名
         * @param writeFile 是否需要將byte數(shù)組寫為文件
         * @param extractDir 如果需要的話可以將byte數(shù)組寫為文件,extractDir為取出數(shù)據被寫的目錄文件
         * @return byte數(shù)組
         * @throws Exception
         */
        public byte[] extractFileFromPak(String pakFilePath,
                        String extractFileName,boolean writeFile,String extractDir) throws Exception{
                File rFile=new File(pakFilePath);
                FileInputStream fis=new FileInputStream(rFile);
                DataInputStream dis=new DataInputStream(fis);
                PakHeader header=readHeader(dis);
                PakFileTable[] fileTable=readFileTable(dis,(int)header.getNumFileTableEntries());

                boolean find=false;
                int fileIndex=0;
                for(int i=0;i<fileTable.length;i++){
                        String fileName=new String(fileTable[i].getFileName()).trim();
                        if (fileName.equals(extractFileName)){
                                find=true;
                                fileIndex=i;
                                break;
                        }
                }
                if (find==false){
                        System.out.println("沒有找到指定的文件");
                        return null;
                }
                else{
                        byte[] buff=readFileFromPak(dis,header,fileTable[fileIndex]);
                        if (writeFile){
                                writeFileFromByteBuffer(buff,extractFileName,extractDir);
                        }
                        else{
                                dis.close();
                                fis.close();
                        }
                        return buff;
                }
        }
        
        
        /**
         * 從pak文件中取出指定的Pak文件的信息
         * @param pakFilePath  pak文件路徑
         * @return 裝載文件頭和文件table數(shù)組的Vector
         * @throws Exception
         */
        public Vector showPakFileInfo(String pakFilePath) throws Exception{
                File rFile=new File(pakFilePath);
                
                FileInputStream fis=new FileInputStream(rFile);
                DataInputStream dis=new DataInputStream(fis);
                
                PakHeader header=readHeader(dis);
                PakFileTable[] fileTable=readFileTable(dis,(int)header.getNumFileTableEntries());

                Vector result=new Vector();
                result.add(header);
                result.add(fileTable);
                return result;
        }
        
        public static void main(String[] argv) throws Exception{
                PakUtil pu=new PakUtil();
                
                //構造文件頭
                char[] signature=new char[PakHeader.SIGNATURE_LENGTH];
                signature=new String("012345").toCharArray();
                char[] uniqueID=new char[PakHeader.UNIQUEID_LENGTH];
                uniqueID=new String("0123456789").toCharArray();
                PakHeader header=new PakHeader();
                header.setSignature(signature);
                header.setNumFileTableEntries(3);
                header.setCipherAction((byte)PakHeader.ADDITION_CIPHERACTION);
                header.setCipherValue((byte)0x0f);
                header.setUniqueID(uniqueID);
                header.setVersion(1.0f);
                header.setReserved(0L);
                
                String[] filePathArray={"F://eclipse3.1RC3//workspace//gmatriXProject_j2se//testFiles//apple.png",
                                "F://eclipse3.1RC3//workspace//gmatrixProject_j2se//testFiles//cushaw.png",
                                "F://eclipse3.1RC3//workspace//gmatrixProject_j2se//testFiles//Flash.png"};
                String extractFilePath="F://eclipse3.1RC3//workspace//gmatrixProject_j2se//testFiles//test.pak";
                //制作Pak文件
                System.out.println("制作Pak文件...");
                pu.makePakFile(filePathArray,extractFilePath,header);
                System.out.println("制作Pak文件完成");
                
                //從Pak文件中取出所有的圖片文件
                Vector pakInfo=pu.showPakFileInfo(extractFilePath);
                header=(PakHeader)pakInfo.elementAt(0);
                System.out.println("Pak文件信息:");
                System.out.println("文件頭:");
                System.out.println(header);
                
                PakFileTable[] fileTable=(PakFileTable[])pakInfo.elementAt(1);
                for(int i=0;i<fileTable.length;i++){
                        System.out.println("文件table["+i+"]:");
                        System.out.println(fileTable[i]);
                }
                
                String restoreDir="F://eclipse3.1RC3//workspace//gmatrixProject_j2se//testFiles//extract//";
                String restoreFileName=null;
                byte[] fileBuff=null;
                for(int i=0;i<fileTable.length;i++){
                        restoreFileName=new String(fileTable[i].getFileName()).trim();
                        System.out.println("從Pak文件中取出"+restoreFileName+"文件...");
                        fileBuff=pu.extractFileFromPak(extractFilePath,restoreFileName,true,restoreDir);
                        System.out.println("從Pak文件中取出"+restoreFileName+"文件保存在"+restoreDir+"目錄");
                }
        }
}


七、PakUtil類(j2me版):

PakUtil.java

package cn.org.matrix.gmatrix.gameLab.util.pak;

import java.io.*;
import java.util.Vector;
/**
* Pak工具類
* 功能:
* 從Pak文件中取出png圖片,構造byte數(shù)組(可以用來構造Image對象)
* @author cleverpig
*
*/
public class PakUtil {
        
        public PakUtil(){
        }
        
        /**
         * 計算文件位移的起始點
         * @return 文件位移的起始點
         */
        private long workOutOffsetStart(PakHeader header){
                //計算出文件頭+文件table的長度
                return PakHeader.size()+header.getNumFileTableEntries()*PakFileTable.size();
        }
        
        /**
         * 從DataInputStream讀取char數(shù)組
         * @param dis DataInputStream
         * @param readLength 讀取長度
         * @return char數(shù)組
         * @throws Exception
         */
        private char[] readCharArray(DataInputStream dis,int readLength) throws Exception{
                char[] readCharArray=new char[readLength];
                
                for(int i=0;i<readLength;i++){
                        readCharArray[i]=dis.readChar();
                }
                return readCharArray;
        }
        
        /**
         * 從PAK文件中讀取文件頭
         * @param dis DataInputStream
         * @return PakHeader
         * @throws Exception
         */
        private PakHeader readHeader(DataInputStream dis) throws Exception{
                PakHeader header=new PakHeader();
                char[] signature=readCharArray(dis,PakHeader.SIGNATURE_LENGTH);
                header.setSignature(signature);
                header.setVersion(dis.readFloat());
                header.setNumFileTableEntries(dis.readLong());
                header.setCipherAction(dis.readByte());
                header.setCipherValue(dis.readByte());
                char[] uniqueID=readCharArray(dis,PakHeader.UNIQUEID_LENGTH);
                header.setUniqueID(uniqueID);
                header.setReserved(dis.readLong());
                return header;
        }
        
        /**
         * 讀取所有的文件table
         * @param dis DataInputStream
         * @param fileTableNumber 文件表總數(shù)
         * @return 文件table數(shù)組
         * @throws Exception
         */
        private PakFileTable[] readFileTable(DataInputStream dis,int fileTableNumber) throws Exception{
                PakFileTable[] fileTable=new PakFileTable[fileTableNumber];
                for(int i=0;i<fileTableNumber;i++){
                        PakFileTable ft=new PakFileTable();
                        ft.setFileName(readCharArray(dis,PakFileTable.FILENAME_LENGTH));
                        ft.setFileSize(dis.readLong());
                        ft.setOffSet(dis.readLong());
                        fileTable[i]=ft;
                }
                return fileTable;
        }
        
        /**
         * 從pak文件讀取文件到byte數(shù)組
         * @param dis DataInputStream
         * @param fileTable PakFileTable
         * @return byte數(shù)組
         * @throws Exception
         */
        private byte[] readFileFromPak(DataInputStream dis,PakHeader header,PakFileTable fileTable) throws Exception{
                dis.skip(fileTable.getOffSet()-workOutOffsetStart(header));
                //
                int fileLength=(int)fileTable.getFileSize();
                byte[] fileBuff=new byte[fileLength];
                int readLength=dis.read(fileBuff,0,fileLength);
                if (readLength<fileLength){
                        System.out.println("讀取數(shù)據長度不正確");
                        return null;
                }
                else{
                        decryptBuff(fileBuff,readLength,header);
                }
                return fileBuff;
        }
        
        /**
         * 使用文件頭中的密碼對數(shù)據進行解密
         * @param buff 被解密的數(shù)據
         * @param buffLength 數(shù)據的長度
         * @param header 文件頭
         */
        private void decryptBuff(byte[] buff,int buffLength,PakHeader header){
                for(int i=0;i<buffLength;i++){
                        switch(header.getCipherAction()){
                        case PakHeader.ADDITION_CIPHERACTION:
                                buff[i]-=header.getCipherValue();
                                break;
                        case PakHeader.SUBTRACT_CIHOERACTION:
                                buff[i]+=header.getCipherValue();
                                break;
                        }
                }
        }
        
        /**
         * 從pak文件中取出指定的文件到byte數(shù)組
         * @param pakResourceURL  pak文件的資源路徑
         * @param extractResourceName pak文件中將要被取出的文件名
         * @return byte數(shù)組
         * @throws Exception
         */
        public byte[] extractResourceFromPak(String pakResourceURL
                        ,String extractResourceName) throws Exception{
                InputStream is=this.getClass().getResourceAsStream(pakResourceURL);
                DataInputStream dis=new DataInputStream(is);
                PakHeader header=readHeader(dis);
//                System.out.println("文件頭:");
//                System.out.println(header);
                PakFileTable[] fileTable=readFileTable(dis,(int)header.getNumFileTableEntries());
//                for(int i=0;i<fileTable.length;i++){
//                        System.out.println("文件table["+i+"]:");
//                        System.out.println(fileTable[i]);
//                }
                boolean find=false;
                int fileIndex=0;
                for(int i=0;i<fileTable.length;i++){
                        String fileName=new String(fileTable[i].getFileName()).trim();
                        if (fileName.equals(extractResourceName)){
                                find=true;
                                fileIndex=i;
                                break;
                        }
                }
                if (find==false){
                        System.out.println("沒有找到指定的文件");
                        return null;
                }
                else{
                        byte[] buff=readFileFromPak(dis,header,fileTable[fileIndex]);
                        return buff;
                }
        }
        
        
        /**
         * 從pak文件中取出指定的Pak文件的信息
         * @param pakResourcePath  pak文件資源路徑
         * @return 裝載文件頭和文件table數(shù)組的Vector
         * @throws Exception
         */
        public Vector showPakFileInfo(String pakResourcePath) throws Exception{
                InputStream is=this.getClass().getResourceAsStream(pakResourcePath);
                DataInputStream dis=new DataInputStream(is);
                
                PakHeader header=readHeader(dis);
                PakFileTable[] fileTable=readFileTable(dis,(int)header.getNumFileTableEntries());

                Vector result=new Vector();
                result.addElement(header);
                result.addElement(fileTable);
                return result;
        }
        
        public static void main(String[] argv) throws Exception{
                PakUtil pu=new PakUtil();
                String extractResourcePath="/test.pak";
                //從Pak文件中取出所有的圖片文件
                Vector pakInfo=pu.showPakFileInfo(extractResourcePath);
                PakHeader header=(PakHeader)pakInfo.elementAt(0);
                System.out.println("Pak文件信息:");
                System.out.println("文件頭:");
                System.out.println(header);
                
                PakFileTable[] fileTable=(PakFileTable[])pakInfo.elementAt(1);
                for(int i=0;i<fileTable.length;i++){
                        System.out.println("文件table["+i+"]:");
                        System.out.println(fileTable[i]);
                }
                
                String restoreFileName=null;
                byte[] fileBuff=null;
                for(int i=0;i<fileTable.length;i++){
                        restoreFileName=new String(fileTable[i].getFileName()).trim();
                        System.out.println("從Pak文件中取出"+restoreFileName+"文件數(shù)據...");
                        fileBuff=pu.extractResourceFromPak(extractResourcePath,restoreFileName);
                        System.out.println("從Pak文件中取出"+restoreFileName+"文件數(shù)據完成");
                }
        }
}


八、源代碼使用簡介:

    Pak過程:j2se版的PakUtil將testFiles目錄中的三個png文件Pak成為test.pak文件。
    UnPak過程:j2se版的PakUtil將testFiles目錄中test.pak文件釋放到testFiles/extract目錄下;j2me版的PakUtil從res目錄中的test.pak文件讀取出其中所包含的3個png文件數(shù)據并裝入到byte數(shù)據,用來構造Image對象,大家請運行PakUtilTestMIDlet.java便可看到輸出的信息。

九、源代碼下載:

j2se版源代碼
Download File

j2sme版源代碼
Download File
資源
·CleverPig的blog:http://blog.matrix.org.cn/page/cleverpig
·Matrix-Java開發(fā)者社區(qū):http://www.matrix.org.cn/
·ProGuard
·j2me.org上的Topic: Give me all your tricks for minimizing jar file size

(出處:http://m.survivalescaperooms.com)



發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 广昌县| 洪雅县| 桓台县| 临安市| 屏南县| 竹溪县| 铁岭县| 丰台区| 大邑县| 交城县| 河西区| 南汇区| 正安县| 怀集县| 织金县| 清水县| 沈阳市| 泗阳县| 青阳县| 旺苍县| 陇南市| 西吉县| 定安县| 五莲县| 青岛市| 阿巴嘎旗| 阜康市| 盘山县| 杭锦后旗| 昭通市| 塔河县| 定结县| 瓦房店市| 平舆县| 项城市| 荣成市| 张家港市| 镇江市| 山阴县| 孟连| 正宁县|