JarInflater.javaダウンロード
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import com.jblend.io.InflateInputStream;
class Application{
public static int toBigEndian( int little ){
return ((little&0xff)<<24)|(((little>>8)&0xff)<<16)|(((little>>16)&0xff)<<8)|((little>>24)&0xff);
}
}
class JarFormatException extends Exception{}
public class JarInflater {
private long startpos;
private DataInputStream ds;
private InputStream in;
public JarInflater(InputStream in) throws JarFormatException, IOException{
ds = new DataInputStream(this.in = in);
((ByteArrayInputStream)in).mark(0);
try{
while (true)
{
while (ds.readByte() != 'P') { }
if (ds.readByte() != 'K') continue;
short signature = ds.readShort();
signature = (short)(((signature & 0xff) << 8) | ((signature & 0xff00) >> 8));
//セントラルディレクトリの終了
if (signature == 0x0605)
{
/*int disknum =*/ ds.readShort();
/*int startdisknum =*/ ds.readShort();
/*int diskdirentry =*/ ds.readShort();
/*int direntry =*/ ds.readShort();
/*int dirsize =*/ ds.readInt();
this.startpos = Application.toBigEndian(ds.readInt()) & 0xffffffffL;
return;
}
}
}catch(EOFException e){
//終端に達してしまった場合不正なJarフォーマットとみなす
throw new JarFormatException();
}
}
public JarInflater(byte [] data) throws JarFormatException, IOException{
this(new ByteArrayInputStream(data));
}
public void close(){
try{ if( ds != null ) ds.close(); } catch (Exception e) {}
ds = null;
}
public long getSize(String name) throws JarFormatException{
try{
((ByteArrayInputStream)in).reset();
ds.skip(startpos);
StringBuffer sb = new StringBuffer();
int read = 0;
byte [] b = new byte[16];
//ストリーム取得時
while (true)
{
int signature = Application.toBigEndian(ds.readInt());
//セントラルディレクトリ
if (signature == 0x02014B50)
{
/*int madever =*/ ds.readShort();
/*int needver =*/ ds.readShort();
/*int option =*/ ds.readShort();
/*int comptype =*/ ds.readShort();
/*int filetime =*/ ds.readShort();
/*int filedate =*/ ds.readShort();
/*int crc32 =*/ ds.readInt();
/*int compsize =*/ ds.readInt();
long uncompsize = Application.toBigEndian(ds.readInt()) & 0xffffffffL;
int fnamelen = (Application.toBigEndian(ds.readShort()) >> 16) & 0xffff;
int extralen = (Application.toBigEndian(ds.readShort()) >> 16) & 0xffff;
int commentlen = (Application.toBigEndian(ds.readShort()) >> 16) & 0xffff;
/*int disknum =*/ ds.readShort();
/*int inattr =*/ ds.readShort();
/*int outattr =*/ ds.readInt();
/*int headerpos =*/ ds.readInt();
//ファイル・ディレクトリ名
{
read = 0;
byte [] fbyte = new byte[fnamelen];
while( read < fnamelen ){
read += ds.read(fbyte, read, fnamelen - read);
}
InputStreamReader isr = new InputStreamReader(
new ByteArrayInputStream(fbyte), "SJIS");
int ch;
sb.delete(0, sb.length());
while ((ch = isr.read()) != -1)
sb.append((char)ch);
try{
isr.close();
}catch (Exception e) {
throw new JarFormatException();
}
if (name.equals(sb.toString()))
return uncompsize;
}
//拡張読み飛ばし
{
read = 0;
while (read < extralen)
{
read += ds.read(b, 0, b.length < (extralen - read) ? b.length : (extralen - read));
}
}
//コメント読み飛ばし
{
read = 0;
while (read < commentlen)
{
read += ds.read(b, 0, b.length < (commentlen - read) ? b.length : (commentlen - read));
}
}
}
else
{
break;
}
}
}catch(EOFException e){
//終端に達してしまった場合不正なJarフォーマットとみなす
throw new JarFormatException();
}catch (Exception e) {
throw new JarFormatException();
}
throw new JarFormatException();
}
public InputStream getInputStream(String name) throws JarFormatException{
try{
((ByteArrayInputStream)in).reset();
ds.skip(startpos);
StringBuffer sb = new StringBuffer();
int read = 0;
byte [] b = new byte[16];
//ストリーム取得時
while (true)
{
int signature = Application.toBigEndian(ds.readInt());
//セントラルディレクトリ
if (signature == 0x02014B50)
{
/*int madever =*/ ds.readShort();
/*int needver =*/ ds.readShort();
/*int option =*/ ds.readShort();
/*int comptype =*/ ds.readShort();
/*int filetime =*/ ds.readShort();
/*int filedate =*/ ds.readShort();
/*int crc32 =*/ ds.readInt();
long compsize = Application.toBigEndian(ds.readInt()) & 0xffffffffL;
/*int uncompsize =*/ ds.readInt();
int fnamelen = (Application.toBigEndian(ds.readShort()) >> 16) & 0xffff;
int extralen = (Application.toBigEndian(ds.readShort()) >> 16) & 0xffff;
int commentlen = (Application.toBigEndian(ds.readShort()) >> 16) & 0xffff;
/*int disknum =*/ ds.readShort();
/*int inattr =*/ ds.readShort();
/*int outattr =*/ ds.readInt();
long headerpos = Application.toBigEndian(ds.readInt()) & 0xffffffffL;
//ファイル・ディレクトリ名
{
read = 0;
byte [] fbyte = new byte[fnamelen];
while( read < fnamelen ){
read += ds.read(fbyte, read, fnamelen - read);
}
InputStreamReader isr = new InputStreamReader(
new ByteArrayInputStream(fbyte), "SJIS");
int ch;
sb.delete(0, sb.length());
while ((ch = isr.read()) != -1)
sb.append((char)ch);
try{
isr.close();
}catch (Exception e) {
throw new JarFormatException();
}
if (name.equals(sb.toString()))
{
((ByteArrayInputStream)in).reset();
ds.skip(headerpos);
signature = Application.toBigEndian(ds.readInt());
//ローカルファイルヘッダ
if (signature == 0x04034B50)
{
ds.readShort();
ds.readShort();
ds.readShort();
ds.readShort();
ds.readShort();
ds.readInt();
ds.readInt();
ds.readInt();
ds.readShort();
extralen = (Application.toBigEndian(ds.readShort()) >> 16) & 0xffff;
//ファイル・ディレクトリ名
{
read = 0;
while (read < fnamelen)
{
ds.readByte();
read++;
}
}
//拡張読み飛ばし
{
read = 0;
while (read < extralen)
{
read += ds.read(b, 0, b.length < (extralen - read) ? b.length : (extralen - read));
}
}
}
else
{
throw new JarFormatException();
}
//圧縮データをbyte配列へ読み込む
ByteArrayOutputStream _comp = new ByteArrayOutputStream(/*(int)compsize*/);
//ZLIB Deflateヘッダ
_comp.write(new byte[]{(byte)0x78,(byte)0x9C});
read = 0;
while(true){
int readsize = ds.read(b);
if( readsize < 0 ) break;
read += readsize;
_comp.write(b, 0, (int)(compsize <= read ? (compsize - (read - readsize)) : readsize));
if( compsize <= read ) break;
}
//残り4byteはCRCかな?
//CRCは出力しなくても良い ってかオプション?
try{
return new InflateInputStream(new ByteArrayInputStream(_comp.toByteArray()));
}catch (Exception e) {
throw new JarFormatException();
}
}
}
//拡張読み飛ばし
{
read = 0;
while (read < extralen)
{
read += ds.read(b, 0, b.length < (extralen - read) ? b.length : (extralen - read));
}
}
//コメント読み飛ばし
{
read = 0;
while (read < commentlen)
{
read += ds.read(b, 0, b.length < (commentlen - read) ? b.length : (commentlen - read));
}
}
}
else
{
break;
}
}
}catch(EOFException e){
//終端に達してしまった場合不正なJarフォーマットとみなす
throw new JarFormatException();
}catch (Exception e) {
throw new JarFormatException();
}
throw new JarFormatException();
}
}
About
彩色アゲハ蝶は東雲千尋の個人サークル 彩色アゲハ蝶のウェブページです。
東方の二次創作でゲームを作っていきます。
その他に作成した3DCG、開発したソフトウェアの公開やサンプルコードなどもアップしています。