자바, 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 파일 을 기록 합 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Is Eclipse IDE dying?In 2014 the Eclipse IDE is the leading development environment for Java with a market share of approximately 65%. but ac...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.