* 签名:6字节char数组
* 版本号:32位float
* 文件table数量:32位整数
* 密码行为:8位字节
* 密码:8位字节
* 文件唯一id:10字节char数组
* 保留位:32位整数(4字节)
* 文件名:30字节char数组
* 文件大小:32位整型
* 文件在pak文件中的位移:32位整数
* 文件数据
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;
}
}
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;
}
}
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+"目录");
}
}
}
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+"文件数据完成");
}
}
}
Java Asp PHP .Net XML C/C++ CGI VB Jsp J2ee J2se J2me EJB Servlet Tomcat Resin Struts Weblogic Eclipse ANT GUI JMS Web servise IDEA Webphere Hibernate Spring Jboss Applet Swing Socket Javamail Perl Ajax P2P 安全 模式 框架 测试 开源 游戏
Windows XP Windows 2000 Windows 2003 Windows Me Windows 9.x Linux UNIX 注册表 操作系统 服务器 应用服务器