자바, jar 패키지 에서 자원 파일 읽 기

코드 에서 일부 자원 파일 (예 를 들 어 그림, 음악, 텍스트 등) 을 읽 고 통합 환경 (Eclipse) 에서 실 행 될 때 문제 가 없습니다.그러나 실행 가능 한 jar 패키지 로 포장 한 후 이 자원 파일 들 을 찾 을 수 없습니다. 다음 코드:
자바 코드 
//   1:  
package edu.hxraid;  
import java.io.*;  
public class Resource {  
    public  void getResource() throws IOException{  
        File file=new File("bin/resource/res.txt");  
        BufferedReader br=new BufferedReader(new FileReader(file));  
        String s="";  
        while((s=br.readLine())!=null)  
            System.out.println(s);  
    }  
}     
        이 코드 는 Eclipse 가 만 든 자바 Project 에 적 혀 있 습 니 다. 디 렉 터 리 는 다음 과 같 습 니 다.
      1、src/
              src/edu/hxraid/Resource.java
      2、bin/
              bin/resource/res.txt
              bin/edu/hxraid/Resource.class
      원본 코드 1 을 실행 하면 자원 파일 res. txt 를 찾 을 수 있 음 이 분명 합 니 다.그러나 우리 가 전체 프로젝트 를 jar 패키지 로 만 든 후에 (ResourceJar. jar) 이 jar 패키지 안의 디 렉 터 리 는:
              edu/hxraid/Resource.class
              resource/res.txt
 
       이 때 jar 패키지 의 Resource. class 바이트 코드: ldc < String "bin/resource/res. txt"> [20] 는 jar 패키지 의 res. txt 위 치 를 찾 을 수 없습니다.빈/디 렉 터 리 를 지 워 도: ldc < String "resource/res. txt"> [20] 는 jar 가방 의 res. txt 에 위치 할 수 없습니다.
      이것 은 주로 jar 패키지 가 폴 더 가 아 닌 단독 파일 이기 때문에 "file:/e:/.../Resource Jar. jar/resource/res. txt"형식의 파일 URL 을 통 해 res. txt 를 찾 을 수 없습니다.따라서 상대 적 인 경로 라 도 jar 파일 에 있 는 txt 파일 을 찾 을 수 없습니다.
 
          그러면 자원 을 jar 패키지 에 넣 으 면 리 소스 jar. jar 가 시스템 의 어떤 경로 에서 든 jar 패키지 의 바이트 코드 프로그램 은 이 가방 의 자원 을 찾 을 수 있 습 니 다.이게 환상 일 까요?
      물론 아 닙 니 다. 우 리 는 클래스 로 더 (ClassLoader) 로 이 점 을 할 수 있 습 니 다.
     
   (1) ClassLoader 는 클래스 로 더 의 추상 적 인 클래스 입 니 다.실행 중 불 러 오 는 클래스 의 실행 정 보 를 동적 으로 가 져 올 수 있 습 니 다.이렇게 말 할 수 있 습 니 다. 리 소스 Jar. jar 의 리 소스 클래스 를 호출 할 때 JVM 은 리 소스 클래스 에 불 러 오고 리 소스 가 실 행 될 때의 정 보 를 기록 합 니 다 (리 소스 가 있 는 jar 패키지 의 경로 정보 포함).ClassLoader 클래스 의 방법 은 이러한 정 보 를 동태 적 으로 얻 는 데 도움 을 줄 수 있 습 니 다.
          ● public URL getResource(String name) 
            주어진 이름 을 가 진 자원 을 찾 습 니 다.자원 은 클래스 코드 를 통 해 코드 기반 과 무관 한 방식 으로 접근 할 수 있 는 데이터 (이미지, 소리, 텍스트 등) 입 니 다.자원 의 URL 대상 을 되 돌려 줍 니 다.
          ● public InputStream getResourceAsStream(String name); 
             지정 한 자원 을 읽 는 입력 흐름 을 되 돌려 줍 니 다.이 방법 은 매우 중요 합 니 다. jar 가방 의 파일 내용 을 직접 얻 을 수 있 습 니 다.
         
     
    (2) ClassLoader 는 abstract 입 니 다. 대상 을 예화 할 수 없고 ClassLoader 를 통 해 위의 두 가지 방법 을 호출 할 수 없습니다.그래서 우리 가 진정 으로 코드 를 쓸 때 는 Class 클래스 의 getResource () 와 getResource AsStream () 방법 을 통 해 ClassLoader 의 getResource () 와 getResource AsStream () 방법 을 의뢰 합 니 다.자, 이제 리 소스 코드 를 다시 써 서 위의 이해 하기 어 려 운 말 이 무슨 뜻 인지 알 아 보 겠 습 니 다.
자바 코드 
//   2:  
package edu.hxraid;  
import java.io.*;  
import java.net.URL;  
public class Resource {  
    public  void getResource() throws IOException{    
              //       URL,  res.txt     bin      
        URL fileURL=this.getClass().getResource("/resource/res.txt");   
        System.out.println(fileURL.getFile());  
    }  
    public static void main(String[] args) throws IOException {  
        Resource res=new Resource();  
        res.getResource();  
    }  
}  
        이 소스 코드 실행 결과:/E:/codeFactory/WANWAN/bin/resource/res.txt  (.../Code Factory/WANWAN/.. 자바 프로젝트 가 있 는 경로 입 니 다)
           우 리 는 이 코드 를 ResourceJar. jar 로 포장 하고 ResourceJar. jar 를 다른 경로 에 두 었 습 니 다 (예 를 들 어 c:\ResourceJar. jar).그리고 자바 프로젝트 를 만 들 고 리 소스 Jar. jar 를 가 져 옵 니 다. jar 패키지 에서 리 소스 류 를 호출 하 는 테스트 코드 를 작성 하 십시오.
자바 코드 
import java.io.IOException;  
import edu.hxraid.Resource;  
public class TEST {  
    public static void main(String[] args) throws IOException {  
        Resource res=new Resource();  
        res.getResource();  
    }  
}  
           이 때 실행 결 과 는 file:/C:/Resource Jar. jar!/resource/res.txt
         
 우리 가 성공 적 으로 실행 할 때 동적 으로 res. txt 의 위 치 를 얻 었 다.그러나 문제 가 생 겼 습 니 다. 다음 코드 를 통 해 res. txt 파일 을 얻 을 수 있 습 니까?                      File f=new File("C:/ResourceJar.jar!/resource/res.txt");             물론 불가능 합 니 다. ".../ResourceJar. jar!/resource/..."는 파일 자원 포 지 셔 닝 문자 의 형식 이 아 닙 니 다. (jar 에 있 는 자원 은 전문 적 인 URL 형식 이 있 습 니 다: jar: < url >!/{entry})따라서 jar 패키지 의 클래스 소스 코드 가 File f = new File (상대 경로) 을 사용 하면;파일 자원 을 찾 을 수 없습니다.소스 코드 1 을 jar 파일 로 포장 한 후 jar 가방 을 호출 할 때 FileNotFound Exception 의 문제점 을 알 리 는 이유 이기 도 합 니 다. 주: 우 리 는 new ImageIcon (클래스. class. getResource ("XX. gif") 을 통 해 ImageIcon 대상 을 얻 을 수 있 지만, jar 파일 의 자원 파일 흐름 을 얻 으 려 면 위의 방법 이 통 하지 않 습 니 다.
         
(3) 리 소스 Jar. jar 의 자원 파일 res. txt 를 일반적인 작업 파일 로 읽 을 수 는 없 지만, Class 류 의 getResource AsStream () 방법 을 통 해 얻 을 수 있 습 니 다. 이 방법 은 jar 의 자원 파일 을 어떻게 읽 는 지, 이 점 은 우리 에 게 투명 합 니 다.우 리 는 Resource. java 를 다음 과 같이 바 꿉 니 다.
자바 코드 
//   3:  
package edu.hxraid;  
import java.io.*;  
public class Resource {  
    public void getResource() throws IOException{  
        //              
        InputStream is=this.getClass().getResourceAsStream("/resource/res.txt");     
       //InputStream is=   .class.getResourceAsStream("XX.config");   
        BufferedReader br=new BufferedReader(new InputStreamReader(is));  
        String s="";  
        while((s=br.readLine())!=null)  
            System.out.println(s);  
    }  
}  
           자바 프로젝트 아래/bin 디 렉 터 리 에 있 는 edu/hxraid/Resource. class 와 자원 파일 resource/res. txt 를 함께 리 소스 Jar. jar 에 포장 합 니 다. jar 패키지 가 시스템 의 모든 디 렉 터 리 에 있 든 jar 패키지 에 있 는 리 소스 류 를 호출 하면 jar 패키지 에 있 는 res. txt 자원 을 얻 을 수 있 습 니 다. 더 이상 res. txt 파일 을 찾 을 수 없습니다.
 (4) 위의 방법 은 jar 에서 자원 파일 을 읽 는 기능 만 제공 하고 jar 에서 자원 파일 을 고 치 는 방법 은 제공 하지 않 습 니 다.
    URL, URLConnection 을 통 해 jar 에 있 는 자원 파일 의 입력 흐름 (InputStream) 과 출력 흐름 (OutputStream) 을 얻 을 수 있 습 니 다. jar 에서 자원 파일 을 읽 을 수 있 을 뿐만 아니 라 jar 에 있 는 자원 파일 도 바 꿀 수 있 습 니 다.
URL url =  .class.getResource("XX.config");
URLConnection  urlConnection=url.openConnection();
//     
InputStream inputStream=urlConnection.getInputStream();
BufferedReader in=new BufferedReader(new InputStreamReader(inputStream,"utf-8"));
//     
OutputStream outputStream=urlConnection.getOutputStream();
PrintStream printStream=new PrintStream(outputStream);

보충: 방금 테스트 해 봤 는데 URL, URLConnection 을 이용 하여 jar 에 있 는 자원 파일 의 출력 흐름 (Output Stream) 을 얻 기 가 쉽 지 않 습 니 다. java. net. Unknown Service Exception: protocol doesn 't support output 는 상기 jar 에 있 는 자원 파일 을 바 꾸 는 방법 이 좋 지 않 기 때 문 입 니 다.
      jar 에 있 는 자원 파일 을 굳이 읽 지 말고 소프트웨어 가 처음 프로그램 을 시작 할 때 만 jar 에 있 는 자원 파일 을 읽 고 사용자 홈 디 렉 터 리 나 사용자 현재 디 렉 터 리 에 백업 한 다음 사용자 디 렉 터 리 에 있 는 자원 파일 을 읽 으 면 됩 니 다.우선, 우 리 는 자원 파일 을 jar 에 포장 합 니 다. 프로그램 이 처음 시작 할 때 jar 에서 자원 파일 정 보 를 읽 고 읽 은 정 보 를 메모리 에 저장 합 니 다. (예 를 들 어 프로그램 을 시작 할 때마다 자원 파일 정 보 를 List 나 Map 집합 에 읽 고 저장 합 니 다) 프로그램 이 실행 되 는 동안 자원 파일 에 대한 업 데 이 트 는 List 와 Map 에 대한 업데이트 입 니 다.프로그램 을 처음 닫 았 을 때 만 메모리 에 저 장 된 자원 정 보 를 System. getProperty (user. home) 사용자 홈 디 렉 터 리 (또는 System. getProperty (user. dir) 사용자 현재 디 렉 터 리) 에 기록 하고 jar 의 자원 파일 과 똑 같은 파일 을 생 성 합 니 다. 나중에 프로그램 이 시 작 될 때 사용자 디 렉 터 리 의 자원 파일 에서 읽 고 씁 니 다.사용자 디 렉 터 리 에 있 는 자원 파일 이 존재 하지 않 을 때 만 jar 의 자원 파일 에서 정 보 를 읽 을 수 있 습 니 다. 따라서 jar 의 자원 파일 은 원본 백업 역할 만 합 니 다.
       물론 이렇게 하면 두 가지 문제 가 있 습 니 다 (1). 즉, 프로그램 이 새 기계 에 설 치 될 때마다 읽 는 자원 파일 정 보 는 jar 의 원시 자원 정보 입 니 다. 중간 에 우리 가 업 데 이 트 했 을 수 있 습 니 다. 해결 방법: 업 데 이 트 된 자원 파일 을 jar 에 다시 포장 합 니 다 (2). 자원 파일 정보 에 대한 업 데 이 트 는 해당 하 는 메모리 데이터 에 대한 업데이트 이기 때 문 입 니 다.프로그램 을 닫 을 때 만 자원 파일 에 쓰 고 수정 한 대로 쓰 지 않 으 면 이러한 결 과 를 초래 할 수 있 습 니 다. 프로그램 이 건장 하지 않 으 면 프로그램 중간 에 bug 가 응답 하지 않 습 니 다. 이 때 는 강제로 닫 을 수 밖 에 없습니다. 업 데 이 트 된 자원 정 보 를 자원 파일 에 쓰 지 않 았 습 니 다!!솔 루 션: 메모리 에 있 는 자원 정 보 를 업데이트 할 때마다 바로 파일 에 기록 합 니 다. 이익: 프로그램 bug 이후 자원 파일 이 최신 임 을 보증 합 니 다. 단점: 이렇게 하면 파일 을 자주 쓰 고 프로그램의 성능 이 떨 어 집 니 다. (꼭 그렇지 는 않 습 니 다. 구체 적 인 프로그램 을 보면 자원 파일 이기 때문에 자주 업데이트 되 지 않 습 니 다)
(5) java. util. jar. JarFile 을 이용 하여????안 해 봤 어 요.
jar 파일 에서 내용 을 읽 고 jar 파일 을 다시 씁 니 다.
먼저 JarFile file = new JarFile (fileName) 을 통 해
그리고 file. entries () 는 jar 파일 내부 요소 의 교체 기 를 얻 을 수 있 습 니 다.이 교체 기와 함께 우 리 는 모든 JarEntry 를 얻 을 수 있 습 니 다.
그리고 InputStream is = jarFile. getInputStream (jarEntry) 을 통 해;이 JarEntry 의 입력 흐름 을 얻 을 수 있 습 니 다.
마지막 으로 is 의 내용 을 JarOutputStream out = new JarOutputStream (new FileOutputStream (distJar) 과 동일 하 게 합 니 다.의 out out. write (int data) 방법 으로 대상 jar 파일 을 기록 합 니 다.

좋은 웹페이지 즐겨찾기