package com.yarin.android.GameEngine.Script.pak;
import java.io.DataInputStream;
import java.io.InputStream;
import java.util.Vector;
/**
* Pak������
* ���ܣ�
* ��Pak�ļ���ȡ��pngͼƬ������byte���飨������������Image����
*
*/
public class PakUtil
{
public PakUtil(){
}
/**
* �����ļ�λ�Ƶ���ʼ��
* @return �ļ�λ�Ƶ���ʼ��
*/
private long workOutOffsetStart(PakHeader header){
//������ļ�ͷ+�ļ�table�ij���
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 ���ݵij���
* @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+"�ļ��������");
}
}
}