分享
 
 
 

跟我学制作Pak文件

王朝other·作者佚名  2008-05-31
窄屏简体版  字體: |||超大  

版权声明:本文可以自由转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本声明

作者: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文件的问题。本人虽学艺不深,但满怀热心的做了一番探索,现将制作Pak文件的看法和方法公布出来,大家多多提意见。

一、什么是Pak文件:

Pak文件就是将多个文件打包为一个单独文件,在这个文件中保存着多个文件的数据,当然还有一些描述文件结构的数据。所以将“Pak”作为文件的后缀是一种常规的用法,大家可以自定义其它的文件后缀。

二、为什么使用Pak文件:

由于MIDP对发布安装的j2me程序大小进行了限制,所以缩小发布程序就意味着能够提供更多的程序或者内容(如图片、音乐)给用户。而通过研究发现zip/jar算法对大文件的压缩率高于对等量的多个小文件的压缩率。

当然还有其它方法,这里简单做一下讨论比如使用混淆器ProGuard的“-overloadaggressively”选项使jar文件缩小,但也会导致一些错误,因为这种方法生成jar中的class符合Java byte code标准,但是与java语法相悖,严重的可能造成一些jre对Object的序列化错误。

所以使用Pak方法将程序中要用到的资源(图片、音乐、文本)组合为单一文件是一个安全有效的方法。而且对于一些商用程序,完全可以在pak文件中对文件数据进行加密,很好的保护了作者和公司的权益。本人的sample中使用了简单的“加减法”加密,对于手机这类设备来讲是一个效率较高的选择。

三、Pak文件的结构:

大家可以自己设计Pak文件结构,本人这里只是抛砖引玉的作个sample。下面就是本人设计的Pak文件结构:

PAK File Header:Pak文件的头部

* 签名:6字节char数组

* 版本号:32位float

* 文件table数量:32位整数

* 密码行为:8位字节

* 密码:8位字节

* 文件唯一ID:10字节char数组

* 保留位:32位整数(4字节)

File Table:Pak文件中包含文件的列表,在一个Pak文件中一个被包含的文件对应一个File Table。

* 文件名:30字节char数组

* 文件大小:32位整型

* 文件在pak文件中的位移:32位整数

Concatenated File Data:按File Table的顺序连接在一起的文件数据。

* 文件数据

四、程序框架:

说明:由于Pak文件的制作和使用分别要使用两个java应用领域:j2se和j2me,所以本人将PakUtil类制作了2个版本(j2se和j2me)。

程序框架如下:

1。PakHeader类,定义了Pak文件头。

2。PakFileTable类,定义Pak文件table。

3。PakUtil类(j2se版),具备两个功能:将多个png图片合成一个Pak文件,并使用简单的加减加密法对其进行加密;从Pak文件中取出png图片,构造byte数组(可以用来构造Image对象)或者写为文件。

PakUtil类(j2me版),具备的功能:从Pak文件中取出png图片,构造byte数组(可以用来构造Image对象)。

五、PakHeader和PakFileTable类:

PakHeader.java:

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

/**

* Pak文件头:

* 结构:

* 签名:6字节char数组

* 版本号:32位float

* 文件table数量:32位整数

* 密码行为:8位字节

* 密码:8位字节

* 文件唯一ID:10字节char数组

* 保留位:32位整数(4字节)

* @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数量

private long numFileTableEntries=0;

//密码使用方法:在原数据上进行加法还是减法

private byte cipherAction=ADDITION_CIPHERACTION;

//密码值

private byte cipherValue=0x00;

//唯一ID

private char[] uniqueID=new char[UNIQUEID_LENGTH];

//保留的4字节

private long reserved=0;

public PakHeader(){

}

/**

* 构造方法

* @param signature 签名

* @param version 版本

* @param numFileTableEntries 文件table数量

* @param cipherAction 密码使用方法

* @param cipherValue 密码值

* @param uniqueID 唯一ID

* @param reserved 保留的2字节

*/

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数量:"+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字节char数组

* 文件大小:32位整型

* 文件在pak文件中的位移:32位整数

* @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数组(可以用来构造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字符数组写入到DataOutputStream中

* @param toWriteCharArray 被写入的char数组

* @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++);

}

/**

* 使用文件头中的密码对数据进行加密

* @param buff 被加密的数据

* @param buffLength 数据的长度

* @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;

}

}

}

/**

* 使用文件头中的密码对数据进行解密

* @param buff 被解密的数据

* @param buffLength 数据的长度

* @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 源文件路径数组

* @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());

}

//写入文件数据

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

* @param dis DataInputStream

* @param readLength 读取长度

* @return char数组

* @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 文件表总数

* @return 文件table数组

* @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数组

* @param dis DataInputStream

* @param fileTable PakFileTable

* @return byte数组

* @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("读取数据长度不正确");

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数组,如果需要的话可以将byte数组写为文件

* @param pakFilePath pak文件路径

* @param extractFileName pak文件中将要被取出的文件名

* @param writeFile 是否需要将byte数组写为文件

* @param extractDir 如果需要的话可以将byte数组写为文件,extractDir为取出数据被写的目录文件

* @return byte数组

* @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数组的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数组(可以用来构造Image对象)

* @author cleverpig

*

*/

public class PakUtil {

public PakUtil(){

}

/**

* 计算文件位移的起始点

* @return 文件位移的起始点

*/

private long workOutOffsetStart(PakHeader header){

//计算出文件头+文件table的长度

return PakHeader.size()+header.getNumFileTableEntries()*PakFileTable.size();

}

/**

* 从DataInputStream读取char数组

* @param dis DataInputStream

* @param readLength 读取长度

* @return char数组

* @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 文件表总数

* @return 文件table数组

* @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数组

* @param dis DataInputStream

* @param fileTable PakFileTable

* @return byte数组

* @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("读取数据长度不正确");

return null;

}

else{

decryptBuff(fileBuff,readLength,header);

}

return fileBuff;

}

/**

* 使用文件头中的密码对数据进行解密

* @param buff 被解密的数据

* @param buffLength 数据的长度

* @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数组

* @param pakResourceURL pak文件的资源路径

* @param extractResourceName pak文件中将要被取出的文件名

* @return byte数组

* @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数组的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+"文件数据...");

fileBuff=pu.extractResourceFromPak(extractResourcePath,restoreFileName);

System.out.println("从Pak文件中取出"+restoreFileName+"文件数据完成");

}

}

}

八、源代码使用简介:

Pak过程:j2se版的PakUtil将testFiles目录中的三个png文件Pak成为test.pak文件。

UnPak过程:j2se版的PakUtil将testFiles目录中test.pak文件释放到testFiles\extract目录下;j2me版的PakUtil从res目录中的test.pak文件读取出其中所包含的3个png文件数据并装入到byte数据,用来构造Image对象,大家请运行PakUtilTestMIDlet.java便可看到输出的信息。

九、源代码下载:

j2se版源代码

Download File

j2sme版源代码

Download File

资源

·CleverPig的blog:http://blog.matrix.org.cn/page/cleverpig

·Matrix-Java开发者社区:http://www.matrix.org.cn/

·ProGuard

·j2me.org上的Topic: Give me all your tricks for minimizing jar file size

(出处:http://www.knowsky.com)

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有