2009-07-24 17 views
3

私は瓶や戦争をしています。Jarファイル内のa * .jarファイルまたはファイルへの入力ストリーム?

私はプログラム的にこのジャーを読んでいます。このジャーの中にジャーを見つけたら、プログラムで読んでみたいと思います。

しかし、JarFileはgetInputStreamのみを提供しています。これはJarFile(Fileファイル)コンストラクタに渡すことはできません。

瓶から瓶を読み取る方法は?

EDIT:私はファイルを何とかクラスローダーから取得することを考えていました。

+0

あなたに何も止まることはありませんが、瓶には他の瓶が入ってはいけません。私はあなたが達成しようとしている機能を実装する別の方法を探します。 http://java.sun.com/j2se/1.5.0/docs/guide/jar/jar.html –

+1

これはwarファイル内にあります。 – blefesd

+0

@Nick Eclipseプラグインは反例です。それらはjarファイルとして配信され、しばしば入れ子になったjarを含んでいます。 –

答えて

1

あなたは、ファイルシステム内のjarファイル、

File tempFile=TempFile.createFile("newJar",".jar"); 

のようなものを作成してそこにストリームを書き込むことができます。その後、あなたは...プログラムは、符号なしのアプレット/ JNLPを実行している場合は、ファイルシステム内のファイルを作成する権限を持っていないので

それについて忘れて...あなたのするJarFile(一時ファイル)を構築し、それを扱うことができる

+0

私はちょうど思い出の中でそれを行うことは可能でしょうか? – blefesd

+0

はい、これは動作しますが、どこかに一時ファイルを書き込むのが最善かどうかはわかりません。一時ファイルを作成せずに他の解決策がない場合は、 – blefesd

+1

はわかりません。ファイルはファイルシステムになければなりません(InMemoryFileのようなものが存在しているとは思いません:))、それらを意図的に作ったので、内部でファイルを渡さずにJarFileをインスタンス化することはできません。 –

6

更新:申し訳ありませんが、これはあなたのニーズには遅すぎる可能性がありますが、私はちょうどコメントであなたの最後の質問を見つけました。そこで、外側のジャーを膨らませる必要なく、ネストされた各エントリがOutputStreamに直接コピーされていることを示すようにこの例を変更しました。

この場合、OutputStreamSystem.outですが、任意のOutputStream(たとえば、ファイル...など)でもかまいません。


一時ファイルを使用する必要はありません。 JarFileの代わりにJarInputStreamを使用し、外部エントリのInputStreamをコンストラクタに渡すと、jarの内容を読み取ることができます。例えば

JarFile jarFile = new JarFile(warFile); 

Enumeration entries = jarFile.entries(); 

while (entries.hasMoreElements()) { 
    JarEntry jarEntry = (JarEntry) entries.nextElement(); 

    if (jarEntry.getName().endsWith(".jar")) { 
     JarInputStream jarIS = new JarInputStream(jarFile 
       .getInputStream(jarEntry)); 

     // iterate the entries, copying the contents of each nested file 
     // to the OutputStream 
     JarEntry innerEntry = jarIS.getNextJarEntry(); 

     OutputStream out = System.out; 

     while (innerEntry != null) { 
      copyStream(jarIS, out, innerEntry); 
      innerEntry = jarIS.getNextJarEntry(); 
     } 
    } 
} 

... 

/** 
* Read all the bytes for the current entry from the input to the output. 
*/ 
private void copyStream(InputStream in, OutputStream out, JarEntry entry) 
     throws IOException { 
    byte[] buffer = new byte[1024 * 4]; 
    long count = 0; 
    int n = 0; 
    long size = entry.getSize(); 
    while (-1 != (n = in.read(buffer)) && count < size) { 
     out.write(buffer, 0, n); 
     count += n; 
    } 
} 
+0

JarEntryをZipFileとして処理できないと思います。エントリー()を取得して作業してください。 – blefesd

+0

試してみてください。瓶は、異なる拡張子とそれがマニフェストを持つ慣習を持つ単なるジッパーです。 –

+0

しかし、JarEntryまたはZipEntryから、あなたは含まれているjarのすべてのエントリを取得することはできません。このように:JarFile jf = new JarFile(jarName); 列挙型 en = jf.entries();私は再帰的に瓶を歩き、それらの瓶で検索する必要があった。 JarEntryから私はエントリーを得ることができません();または少なくとも私は方法を見つけていない。 – blefesd

-1

再帰的に新しいjarファイルを読むためにもう一度するJarFileを使用します。例の場合、

import java.io.File; 
import java.io.IOException; 
import java.io.InputStream; 
import java.util.Enumeration; 
import java.util.jar.JarEntry; 
import java.util.jar.JarFile; 
import java.util.zip.ZipEntry; 


public class JarReader { 

public static void readJar(String jarName) throws IOException { 
    String dir = new File(jarName).getParent(); 
    JarFile jf = new JarFile(jarName); 
    Enumeration<JarEntry> en = jf.entries(); 
    while(en.hasMoreElements()) { 
     ZipEntry ze = (ZipEntry)en.nextElement(); 
     if(ze.getName().endsWith(".jar")) { 
      readJar(dir + System.getProperty("file.separator") + ze.getName()); 
     } else { 
      InputStream is = jf.getInputStream(ze); 
      // ... read from input stream 
      is.close(); 
      System.out.println("Processed class: " + ze.getName()); 
     } 
    } 
} 

public static void main(String[] args) throws IOException { 
    readJar(args[0]); 
} 

} 
+1

これは動作しません。JarFile jf = new JarFile(jarName); JarFileは、システム上のjarName(ファイル)を想定しています。 そして、あなたはjava.util.zip.ZipExceptionを取得します:システムが指定されたパスを見つけることができません – blefesd

0

一般的には、InputStreamに到達してから作業してください。これにより、ほとんどの「jar in jar in web server」の問題などを抽象化することができます。

この場合は、明らかにJarFile.getInputStream()とJarInputStream()です。

関連する問題