彩色アゲハ蝶
Top>PROGRAM> CLDC+MIDP+MEXA対応JarInflater
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、開発したソフトウェアの公開やサンプルコードなどもアップしています。