Java Tip 49 : JAR 및 zip 아카이브에서 Java 리소스를 추출하는 방법

대부분의 Java 프로그래머는 JAR 파일을 사용하여 Java 솔루션을 구성하는 다양한 리소스 (즉, .class 파일, 사운드 및 이미지)를 모두 번들로 묶을 때 얻을 수있는 이점을 잘 알고 있습니다. (JAR 파일에 익숙하지 않은 경우 아래 리소스 섹션을 확인하십시오.) JAR 파일을 트릭 가방에 막 통합하기 시작한 사람들이 가장 많이 묻는 질문은 "어떻게 이미지를 항아리?" 우리는 그 질문에 답하고 JAR에서 리소스를 추출하는 것을 매우 간단하게 만드는 클래스를 제공 할 것입니다!

GIF 이미지로드

애플리케이션에서 사용하려는 .gif 이미지 파일이 포함 된 JAR 파일이 있다고 가정 해 보겠습니다. JarResources를 사용하여 JAR에서 이미지 파일에 액세스하는 방법은 다음과 같습니다.

JarResources jar = 새 JarResources ( "Images.jar"); 이미지 로고 = Toolkit.getDefaultToolkit (). createImage (jar.getResource ( "logo.gif");

이 코드 스 니펫은 JarResources-사용하려는 리소스를 포함하는 JAR 파일로 초기화 된 객체를 생성 할 수 있음을 보여줍니다 Images.jar. 그런 다음이 JarResources'getResource()메서드를 사용하여 AWT 툴킷의 createImage()메서드에 대한 logo.gif 파일의 원시 데이터를 제공합니다 .

명명에 대한 참고 사항

JarResource는 Java 1.1에서 제공하는 다양한 기능을 사용하여 JAR 및 zip 아카이브 파일을 조작하는 방법에 대한 합리적으로 간단한 예입니다.

이름 지정에 대한 빠른 참고. Java의 아카이브 지원은 실제로 널리 사용되는 zip 아카이브 형식을 사용하여 시작되었습니다 ( "Java Tip 21 : 아카이브 파일을 사용하여 애플릿로드 속도 향상"참조). 따라서 원래는 아카이브 파일을 조작하기위한 Java 지원을 구현할 때 모든 클래스와 기타 항목이 java.util.zip 패키지에 배치되었습니다. 이러한 클래스는 ""로 시작하는 경향이 있습니다 Zip. 그러나 Java 1.1로 이동하는 과정에서 아카이브 이름이 Java에 더 중점을 두도록 변경되었습니다. 따라서 이제 JAR 파일이라고 부르는 것은 기본적으로 zip 파일입니다.

작동 원리

JarResources클래스 의 중요한 데이터 필드 는 지정된 JAR 파일의 내용을 추적하고 저장하는 데 사용됩니다.

public final class JarResources {public boolean debugOn = false; private Hashtable htSizes = new Hashtable (); private Hashtable htJarContents = new Hashtable (); 개인 문자열 jarFileName;

따라서 클래스의 인스턴스화는 JAR 파일의 이름을 설정 한 다음 init()모든 실제 작업을 수행 하기 위해 메서드를 호출 합니다.

public JarResources (String jarFileName) {this.jarFileName = jarFileName; init (); }

이제이 init()메소드는 지정된 JAR 파일의 전체 내용을 해시 테이블 (리소스 이름을 통해 액세스)로로드합니다.

이것은 상당히 무거운 방법이므로 좀 더 자세히 살펴 보겠습니다. 이 ZipFile클래스는 JAR / zip 아카이브 헤더 정보에 대한 기본 액세스를 제공합니다. 이것은 파일 시스템의 디렉토리 정보와 유사합니다. 여기에서의 모든 항목을 열거 하고 아카이브의 각 리소스 크기로 htSizes 해시 테이블을 ZipFile구축합니다 .

private void init () {try {ZipFile zf = new ZipFile (jarFileName); 열거 e = zf.entries (); while (e.hasMoreElements ()) {ZipEntry ze = (ZipEntry) e.nextElement (); if (debugOn) {System.out.println (dumpZipEntry (ze)); } htSizes.put (ze.getName (), new Integer ((int) ze.getSize ())); } zf.close ();

다음으로, ZipInputStream클래스를 사용하여 아카이브에 액세스합니다 . 이 ZipInputStream수업은 우리가 아카이브의 각 개별 리소스를 읽을 수 있도록 모든 마법을 수행합니다. 각 리소스를 구성하는 아카이브에서 정확한 바이트 수를 읽고 해당 데이터를 리소스 이름으로 액세스 할 수 있는 htJarContents 해시 테이블에 저장합니다 .

FileInputStream fis = new FileInputStream (jarFileName); BufferedInputStream bis = new BufferedInputStream (fis); ZipInputStream zis = new ZipInputStream (bis); ZipEntry ze = null; while ((ze = zis.getNextEntry ())! = null) {if (ze.isDirectory ()) {계속; } if (debugOn) {System.out.println ( "ze.getName () ="+ ze.getName () + ","+ "getSize () ="+ ze.getSize ()); } int size = (int) ze.getSize (); // -1은 알 수없는 크기를 의미합니다. if (size ==-1) {size = ((Integer) htSizes.get (ze.getName ())). intValue (); } byte [] b = new byte [(int) size]; int rb = 0; int 청크 = 0; while (((int) size-rb)> 0) {chunk = zis.read (b, rb, (int) size-rb); if (chunk ==-1) {break; } rb + = 청크; } // 내부 리소스 해시 테이블에 추가 htJarContents.put (ze.getName (), b); if (debugOn) {System.out.println (ze.getName () + "rb ="+ rb + ", size ="+ size + ", csize ="+ ze.getCompressedSize ()); }}} catch (NullPointerException e) {System.out.println ( "done."); } catch (FileNotFoundException e) {e.printStackTrace (); } catch (IOException e) {e.printStackTrace (); }}

각 리소스를 식별하는 데 사용되는 이름은 아카이브에있는 리소스의 정규화 된 경로 이름입니다. 예를 들어 패키지의 클래스 이름이 아닙니다 . 즉 ZipEntry, java.util.zip 패키지 의 클래스 이름이 아닙니다 . "java.util.zip.ZipEntry"가 아닌 "java / util / zip / ZipEntry"로 이름을 지정하십시오.

코드의 마지막 중요한 부분은 간단한 테스트 드라이버입니다. 테스트 드라이버는 JAR / zip 아카이브 이름과 리소스 이름을 사용하는 간단한 애플리케이션입니다. 아카이브에서 리소스를 찾으려고 시도하고 성공 또는 실패를보고합니다.

public static void main (String [] args) throws IOException {if (args.length! = 2) {System.err.println ( "usage : java JarResources"); System.exit (1); } JarResources jr = new JarResources (args [0]); 바이트 [] buff = jr.getResource (args [1]); if (buff == null) {System.out.println ( ""+ args [1] + "를 찾을 수 없습니다."); } else {System.out.println ( ""+ args [1] + "(length ="+ buff.length + ")를 찾았습니다."); }}} // JarResources 클래스의 끝.

그리고 거기에 있습니다. JAR 파일에 숨겨진 리소스 사용과 관련된 모든 혼란을 숨기는 사용이 간편한 클래스입니다.

독자를위한 연습

이제 아카이브 파일에서 리소스를 추출하는 느낌을 받았으므로 JarResources클래스 를 수정하고 확장 할 때 탐색 할 수있는 몇 가지 지침은 다음과 같습니다.

  • 건설 중에 모든 것을 적재하는 대신 지연 적재를 수행하십시오. 큰 JAR 파일의 경우 구성 중에 모든 파일을로드 할 메모리가 충분하지 않을 수 있습니다.
  • 대신 단순히 같은 일반적인 접근 방법을 제공으로 getResource(), 우리는 다른 자원 고유의 접근을 제공 할 수있다 - 예를 들어 getImage(), 자바 반환 Image객체, getClass()자바 반환 Class(사용자 정의 클래스 로더의 도움으로) 객체를, 등등. JAR 파일이 충분히 작 으면 확장명 (.gif, .class 등)을 기반으로 모든 리소스를 미리 빌드 할 수 있습니다.
  • 일부 메소드는 다음을 포함하여 주어진 JAR 파일 자체 (기본적으로 래퍼 ZipFile) 에 대한 정보를 제공해야 합니다. Jar / zip 항목 수; 리소스의 모든 이름을 반환하는 열거 자; 특정 항목의 길이 (및 기타 속성)를 반환하는 접근 자 인덱싱을 허용하는 접근 자 등이 있습니다.
  • JarResources애플릿에서 사용하도록 확장 할 수 있습니다. 애플릿 매개 변수와 URLConnection클래스 를 활용 하면 아카이브를 로컬 파일로 여는 대신 네트워크에서 JAR 컨텐츠를 다운로드 할 수 있습니다. 또한이 클래스를 사용자 정의 Java 컨텐츠 핸들러로 확장 할 수 있습니다.

결론

JAR 파일에서 이미지를 추출하는 방법을 알고 싶다면 이제 방법이 있습니다. JAR 파일로 이미지를 처리 ​​할 수있을뿐만 아니라이 팁에서 제공하는 새 클래스 를 사용하여 JAR의 모든 리소스에서 추출 마법을 사용 합니다 .

Arthur Choi는 현재 IBM에서 자문 프로그래머로 일하고 있습니다. 그는 SamSung Network Laboratory와 MITRE를 포함한 여러 회사에서 근무했습니다. 그가 작업 한 다양한 프로젝트는 클라이언트 / 서버 시스템, 분산 개체 컴퓨팅 및 네트워크 관리입니다. 그는 다양한 운영 체제 환경에서 여러 언어를 사용했습니다. 그는 1981 년 FORTRAN IV 및 COBOL로 프로그래밍을 시작했습니다. 나중에 그는 C 및 C ++로 전환했으며 약 2 년 동안 Java로 작업했습니다. 그는 광역 네트워크를 통한 데이터 저장소 영역과 인터넷을 통한 병렬 및 분산 처리 (에이전트 기반 프로그래밍 사용)의 Java 애플리케이션에 가장 관심이 있습니다. 직원이자 컨설턴트이자 회사 대표 인 John Mitchell은 지난 10 년 동안 최첨단 컴퓨터 소프트웨어 개발에 투자했습니다.다른 개발자에게 조언과 교육을 제공합니다. 그는 Java 기술, 컴파일러, 인터프리터, 웹 기반 애플리케이션 및 인터넷 상거래에 대한 컨설팅을 제공했습니다. John은 Making Sense of Java : A Guide for Managers and the Rest of Us를 공동 저술했으며 프로그래밍 저널에 기사를 게재했습니다. JavaWorld에 대한 Java Tips 칼럼을 작성하는 것 외에도 그는 comp.lang.tcl.announce 및 comp.binaries.geos 뉴스 그룹을 관리합니다.

이 주제에 대해 더 알아보기

  • 다음은 클래스 파일 JarResources.java//www.javaworld.com/javatips/javatip49/JarResources.java입니다.
  • JAR //www.javasoft.com/products/jdk/1.1/docs/guide/jar/index.html
  • Java의 아카이브 지원에 대한 자세한 내용은 "Java Tip 21 아카이브 파일을 사용하여 애플릿로드 속도 향상"을 참조하십시오. //www.javaworld.com/javatips/jw-javatip21.html

이 이야기는 "Java Tip 49 : JAR 및 zip 아카이브에서 Java 자원을 추출하는 방법"은 원래 JavaWorld에서 게시했습니다.