MY-NOTEBOOK

Tuesday, April 18, 2006

jar にリソースファイルを含める方法、それをプログラムから使う方法(Java,resource,jar)

一般向けに配布するプログラムを作る場合、プログラム中で使用する画像やファイルをjarに含めておくとユーザにとっては取り扱いが非常に楽になります。(jar一個をコピーするだけで済みます)

開発者の方は、jarにリソースを含めたり、含めたリソースからデータを読み出すコードを書かないといけないので、多少負担が増えます。

jarに含めたいリソースの例

  • ツールバーアイコン
  • テンプレートファイル
  • サンプルデータ一式
  • ヘルプファイル一式

テキストデータの場合

簡単な例として、HelloWorld.txtをjarに含めるようにして、
そのファイルをプログラム中から読み出す場合。

STEP1 jarにリソースを含める

antでjarタスクに以下のように記述します。

    <jar destfile="test.jar">
    	<fileset file="./HelloWorld.txt" /> 
    </jar>

これで、test.jarに カレントディレクトリに用意した HelloWorld.txt を含めることができます。

build.xml全体では、以下のようになります。

build.xml

<project default="jar">

	<target name="init">
		<property name="build.src" value="./src"/>
		<property name="build.dest" value="./bin"/>
	</target>
	<target name="clean" depends="init">
		<delete file="test.jar" />
		<delete dir="${build.dest}" />
	</target>

	<target name="compile" depends="init">
		<mkdir dir="${build.dest}" />
		<javac destdir="${build.dest}" 
			srcdir="${build.src}" 
			>
			<include name="**/*.java" />
		</javac>
	</target>
	<target name="jar" depends="compile" >
		<jar destfile="test.jar">
			<fileset file="./HelloWorld.txt" /> 
			<zipfileset dir="${build.dest}" />
			<manifest>
				<attribute name="Main-Class" value="Test" />
			</manifest>
		</jar>
	</target>
</project>

STEP2 プログラム中から利用する

以下のようにして、STEP1で用意しておいた HelloWorld.txt のInputStreamを得ることができます。

InputStream is=getClass().getClassLoader().getResourceAsStream("HelloWorld.txt");

プログラム全体では、以下のようになります。

Test.java

import java.io.*;

public class Test{
	
	public Test(){
		try{
			InputStream is=getClass().getClassLoader().getResourceAsStream("HelloWorld.txt");
			BufferedReader br=new BufferedReader(new InputStreamReader(is,"UTF-8"));
			while(true){
				String line=br.readLine();
				if(line==null){
					break;
				}
				System.out.println(line);
			}
			br.close();
			is.close();
		}
		catch(Exception ex){
			ex.printStackTrace();
		}
	}

	static public void main(String[] s){
		new Test();
	}

}

画像の場合

ツールバーで使用するアイコン画像をjarに含めておく、などといった使い方が一般的だと思います。
jarに含める方法は、テキストデータの場合と同じですが、プログラム中から取り出すには、取り出したInputStreamをイメージに変換しなければいけない点が違います。

STEP1 複数の画像ファイルをjarに含める

テキストデータの場合と同じですが、複数のイメージファイルを含めるため、 icons/ というディレクトリ以下にあるイメージファイル(*.png)全部を対象とします。

    <jar destfile="test.jar">
         <fileset dir="./icons" includes="*.png" />
    </jar>

build.xml 全体では以下のようになります。

build.xml

<project default="jar">

	<target name="init">
		<property name="build.src" value="./src"/>
		<property name="build.dest" value="./bin"/>
	</target>
	<target name="clean" depends="init">
		<delete file="test.jar" />
		<delete dir="${build.dest}" />
	</target>

	<target name="compile" depends="init">
		<mkdir dir="${build.dest}" />
		<javac destdir="${build.dest}" 
			srcdir="${build.src}" 
			>
			<include name="**/*.java" />
		</javac>
	</target>
	<target name="jar" depends="compile" >
		<jar destfile="test.jar">
			<fileset dir="./icons" includes="*.png" />
			<zipfileset dir="${build.dest}" />
			<manifest>
				<attribute name="Main-Class" value="Test" />
			</manifest>
		</jar>
	</target>
</project>

STEP2 プログラム中から利用する

以下のようにして、STEP1で用意しておいた new.png のURLを得ることができます。

URL url=getClass().getClassLoader().getResource("new.png");
ImageIcon icon=new ImageIcon(url);

プログラム全体では、以下のようになります。

Test.java

import java.io.*;
import java.net.*;
import javax.swing.*;

public class Test extends JFrame{
	
	public Test(){
		try{
			URL url=getClass().getClassLoader().getResource("new.png");
			ImageIcon icon=new ImageIcon(url);

			JLabel label=new JLabel(icon);
			getContentPane().add(label);
		}
		catch(Exception ex){
			ex.printStackTrace();
		}
	}

	static public void main(String[] s){
		Test t=new Test();
		t.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		t.pack();
		t.setVisible(true);
	}

}

SWTでウインドウのアイコンイメージを設置する場合

jarに埋め込んでおいた icon.png をSWTのウインドウアイコンとして使う場合は、以下のようにします。

    try{
    	InputStream is=getClass().getClassLoader().getResourceAsStream("icon.png");
    	ImageData data=new ImageData(is);
    	Image i=new Image(shell.getDisplay(),data);
    	shell.setImage(i);
    	i.dispose();
    	is.close();
    }
    catch(Exception ex){
    	ex.printStackTrace();
    }

Jar に含めた画像をJEditorPaneで使う方法

操作方法ヘルプなどをHTMLで書いて、JEditorPaneで表示させる場合、そのヘルプ内で使用する画像データを jar に含めておくと、プログラム配布時の取り扱いが簡単になります。( executable jar 一個の配布で済むので)

© 2006-2012 Tomoaki Oshima