Jar 파일에 리소스를 포함하여 배포하였을 경우 그 리소스에 접근하는 방법입니다.

예제코드:
package com.pmguda.resjar;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.sound.sampled.*;
import java.net.*;

public class JarResourceLoading extends JFrame
    implements ActionListener {

    JButton button;
    ImageIcon buttonIcon;
    Clip buhClip;

    public final static String SOUND_PATH = "res/gudaMid.wav";
    public final static String IMAGE_PATH = "res/gudaImage.jpg";

    public JarResourceLoading () {
        super ("Resources from .jar");
        // get image and make button
        URL imageURL = getClass().getClassLoader().getResource (IMAGE_PATH);
        System.out.println ("found image at " + imageURL);
        buttonIcon = new ImageIcon (imageURL);
        button = new JButton ("Click to Buh!", buttonIcon);
        button.setHorizontalTextPosition (SwingConstants.CENTER);
        button.setVerticalTextPosition (SwingConstants.BOTTOM);
        button.addActionListener (this);
        getContentPane().add (button);
        // load sound into Clip
        try {
            URL soundURL = getClass().getClassLoader().getResource (SOUND_PATH);
            System.out.println ("found sound at " + soundURL);
            Line.Info linfo = new Line.Info (Clip.class);
            Line line = AudioSystem.getLine (linfo);
            buhClip = (Clip) line;
            AudioInputStream ais = AudioSystem.getAudioInputStream(soundURL);
            buhClip.open(ais);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void actionPerformed (ActionEvent e) {
        System.out.println ("click!");
        if (buhClip != null) {
            buhClip.setFramePosition (0);
            buhClip.start();
        }
        else
            JOptionPane.showMessageDialog (this,
                                           "Couldn't load sound",
                                           "Error",
                                           JOptionPane.ERROR_MESSAGE);
    }

    public static final void main (String[] args) {
        JFrame frame = new JarResourceLoading();
        frame.pack();
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

}
그림 1.


이클립스에서 jar 파일로 자동 배포 하였습니다. Jar 파일의 내부 구조도 이와 비슷하다.(압축을 풀어보면 알게된다.)

jar 파일안에 있는 이미지의 URL 은  Jar:file:/D:/resource.jar!/res/gudaImage.jpg

위의 코드에 대해 자세히 알아보고자 다른 자료를 찾아보았다.
다른 자료를 조금 인용하기 위해 긁어왔다.. 영문이다. ㅡㅡ;
해석해보면 그리 어렵지 않다. 위의 코드와 조금 다른 부분이 있을것이다. 잘 생각해 보자.


If you want to access a resource (configuration files, images, etc.) then you can certainly put it in a jar file, provided that jar file is in your classpath.

Then to access the resource, you can get a URL to it like this:
            URL url = this.getClass().getResource("/hello.jpg");
or you can get an InputStream to read it like this:
            InputStream is = this.getClass().getResourceAsStream("/app.properties");
Note that these methods will search for the resource in the directory tree relative to the package that "this" is in, so you will generally need the leading "/" to avoid that. But as for executable files in a jar file, forget it, there's no way to execute them from there. You can copy them out to a file and execute them from there, but that's the best you can do.


여기서 짚고 넘어가야 할 것은
패키지: com.pmguda.resjar
클래스: com.pmguda.resjar.JarResourceLoading
1.   getClass().getResource("gudaImage.jpg");
      현재 클래스의 위치에서 리소스를 찾는다
     클래스와 리소스의 위치가 같은 곳에 존재해야 한다.

2.   getClass().getResource("/res/gudaImage.jpg");
     패키지와 동일 루트에서 검색
3.   getClass().getClassLoader.getResource("res/gudaImage.jpg"); 
      패키지와 동일 루트에서의 상대 위치를 나타낸다.

java.lang.Class.getResource(String name)



번역이 완전하지가 않아 이해하기 어려울듯 하다.

java.lang.Class.getResource(String name)에서
name 가 "/gudaImage.jpg" 일 경우 절대 경로명(/gudaImage.jpg)으로 사용되고
"gudaImage.jpg" 일 경우 현 클래스의 위치에서 시작하는 상대경로가 되겠지요 이를
절대경로로
나타내면 (/com/pmguda/resjar/gudaImage.jpg)

java.lang.ClassLoader.getResource(String name)



1. getClass().getResource("/res/gudaImage.jpg"); 
2. getClass().getClassLoader.getResource("res/gudaImage.jpg"); 
동일한 URL을 리턴한다. 2번예시에서 앞에 "/" 을 넣어 시작하지 말도록 하자.
2번은 항상 상대경로만 인식하여 사용된다고 명심하시길..
ex)getClass().getClassLoader.getResource("/res/gudaImage.jpg");  

조금더 알아보고자 한다면 ClassLoader 에 대해 알아보는 것도 좋을듯 하다.
http://www.ibm.com/developerworks/kr/series/j-dclp.html?ca=dnn-krt-20071226




댓글을 달아 주세요

  1. Favicon of http://devyongsik.tistory.com BlogIcon dev용식  댓글주소  수정/삭제  댓글쓰기

    안녕하세요? 검색하다 찾아왔는데요.. 오늘 하루종일 찾아헤매던 자료라서요..
    죄송하지만 질문 하나만 드리고 싶은데요~

    getClass().getResource()와
    getClass().getClassLoader().getResource()의 차이가 뭘까요?

    어느 상황에서는 위에 것을 쓰고
    어느 상황에서는 아래 것을 쓰는 등의 레퍼런스가 있을까요 ^^

    혹시 아시면 답변을 좀 부탁드리겠습니다..^^;;

    2008.12.03 18:06
    • Favicon of https://www.pmguda.com BlogIcon Ishaya seon 2008.12.04 10:39 신고  댓글주소  수정/삭제

      1. getClass().getResource("/res/gudaImage.jpg" );
      2. getClass().getClassLoader.getResource("res/gudaImage.jpg" );

      지금은 동일 구조상에서 둘다 같은 결과를 리턴하게 됩니다.
      1번은 this.getClass() 는 실행시 객체의 클래스를 리턴하게 되죠. 해당 클래스를 기준으로 getResource메소드의 인자가 상대경로가 되는것이고 인자의 맨앞에"/" 이 붙었을때는 절대경로가 되는 것이라고 보심 될듯하네요. 클래스를 기준으로 하는 상대경로 및 절대경로.

      2번 getClassLoader 가 들어가 있죠. 클래스의 클래스로더의 를 리턴하는 메소드이구요. ClassLoader.getResource 메소드 인데요. 1번처럼 클래스가 기준이 되는것이 아니라 클래스로더 기준으로 생각하는게 간단할것 같네요. 므튼 getClassLoader.getResource 메소드는 "/" 로 시작할 수 없고 항상 상대경로로 인식한다는 것입니다.

      좀더 근본적으로 알고 싶으시면 ClassLoader에 대해 알아 보시면 될듯 하구요. 그냥 사용상의 차이점은

      1번은 현 클래스의 위치를 기준으로 한 상대경로이고,
      "/"를 맨앞에 붙었을시는 절대경로 이구요.

      2번은 "/"로 시작할 수 없고 항상 상대경로로 인식한다.(단 상대경로는 현 클래스의 위치가 아니라 최상위라고 생각하심 될듯 하네요.)

      제가 답변이 장황하네요. ^^;; 제 지식의 부족함입니다.

    • Favicon of http://devyongsik.tistory.com BlogIcon dev용식 2008.12.05 20:53  댓글주소  수정/삭제

      감사합니다 ^^
      일반적으로 build path로 지정되어 있는 곳의 class들을 하나의 ClassLoader가 불러오기 때문에 딱히 비교할 것이 없어서 그렇게 되는 것 같네요 ^^

      저도 많이 궁금해서 찾아다니다가
      http://www.javaworld.com/javaworld/javaqa/2002-11/02-qa-1122-resources.html

      이 사이트를 발견했는데 내용이 좋은 것 같습니다.

      답변 주셔서 정말 감사드립니다 ^^

    • Favicon of https://www.pmguda.com BlogIcon Ishaya seon 2008.12.15 18:00 신고  댓글주소  수정/삭제

      제 설명이 미흡해서..^^

      이렇게 댓글 달아주시고 좋은 자료 알려주셔서 감솨 ^^

  2. bini  댓글주소  수정/삭제  댓글쓰기

    다른 패키지에 있는 이미지를 로딩하려니 계속 null 값이 들어오던데 님 소스는 정상 작동 된다는 말씀인가요? 위와같이 하면 getClass() 시점에서 path가 이미
    JarResourceReading 클래스가 있는 페키지로 잡히기 때문에 res 폴더는 접근이 불가능한
    걸로 알고 있는데요? 제가 실력이 부족한건지 모르겠지만 암튼
    제가 테스트 해본결과는 그렇습니다만....

    2009.05.15 01:41
    • Favicon of https://www.pmguda.com BlogIcon Ishaya seon 2009.05.15 09:15 신고  댓글주소  수정/삭제

      글을 잘 읽어보시면 getClass().getResource()와
      getClass().getClassLoader().getResource()에 대해서 작성된 부분을 잘이해하시면 될것 같습니다.
      클래스로더에 대해 좀 더 알아보시면 좋을것 같구요.

      메일이라도 남겨주시면 자료도 보내드릴텐데..
      아쉽네요.^^;

  3. bini  댓글주소  수정/삭제  댓글쓰기

    yoonbin82@naver.com 시간되시면 자료 부탁드립니다.
    classLoader 를 이용해도 같은 결과만 나오네요.

    2009.05.16 19:33
  4. bini  댓글주소  수정/삭제  댓글쓰기

    아..해결했네요..-0- getClass().getClassLoader() 의 default Path 가 프로젝트/bin 폴더 였군요. res 폴더를 패키지처럼 사용하니 정상적으로되네요...암튼 감사드립니다.

    2009.05.16 19:45

1 2 3 4 5 6 7 8 9 10 ··· 49 

글 보관함

카운터

Total : 1,733,629 / Today : 51 / Yesterday : 111
get rsstistory!