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、開発したソフトウェアの公開やサンプルコードなどもアップしています。