2014년 5월 4일 업데이트

압축 풀 때 디렉토리 못찾는 버그 수정해서 다시 올림.

CompressionUtil.java


고친다 고친다 생각만 하다가 오랜만에 로그인한 김에...

-------------------------------------------------------------


java.util.zip.* 관련 클래스를 이용하면 디렉토리나 파일명에 한글이 있을 경우 무참히 깨지며 압축과 해제가 제대로 안된다.

내부적으로 UTF-8 인코딩을 이용해서 스트림을 다루기 때문이라고 하는데, 이때문에 commons-compress 에서 제공하는 컴포넌트를 이용한다.

API는 java.util.zip.* 의 클래스와 거의 유사해서 이용하는데 별도의 학습은 불필요한듯.

아예 아래와 같이 유틸리티 클래스를 만들어두면 더 편하다.

(아래 파일은 압축 풀 때 오류 발생하는 경우 있음. 위에 첨부한 파일이 업데이트 버전입니다.)

CompressionUtil.java


사용방법은 다양한데, 아래와 같이 하면 simple과 하위 디렉토리, 파일을 전부 압축해서 E:/test 밑에 simple.zip 파일을 생성한다.

압축 해제는 다음과 같이 할 경우

E:/test 밑에 압축이 풀린다. 또는 아래와 같이 별도의 디렉토리에 압축을 풀 수도 있다.

이외에 charset 을 지정해주거나 압축시 최상위 디렉토리를 압축 파일에 포함할지, 아니면 최상위 디렉토리의 하위디렉토리부터 압축할지도 선택할 수 있다. 소켓을 통한 스트림 전송을 위해서 OutputStream과 InputStream 을 이용할 수도 있다.


Posted by yeori

댓글을 달아 주세요

  1. 2010.11.03 10:01

    감사합니다. 많은 도움이 되었습니다 ^^

    출처를 밝히고 내용 퍼갑니다.

    • 2010.11.04 12:45 신고

      아 넵. 혹시 삑사리 나는 부분 있으면 알려주시길 바랍니다 ^^

  2. 스윙
    2011.07.08 15:59

    분명히 경로를 제대로 썼습니다.
    다시한번봐도 제대로 썼는데..
    unzip(new File("C:/Documents and Settings/Administrator/Application Data/specil/active/stop.zip),new File("C:/install"));
    이렇게 하면 오류가 뜨내요;;
    그런데 또
    unzip(new File("C:/too.zip),new File("C:/install"));
    이렇게 하면 되내요; 왜이러죠? 해결방법좀 알려주세요ㅠㅠ

    • 2011.07.12 00:29 신고

      경로명을 String으로 주지 마시구요,

      String을 File 인스턴스로 만든 후에 해보세요.

      아래 메소드를 이용하는거니까요....

      public void unzip(File zippedFile, File destDir) throws IOException ...

  3. 스윙
    2011.07.12 14:24

    어흑 용량문제인것 같네요... 용량이 70KB인 압축파일은 잘되는데
    1040KB는
    java.io.IOException: 지정된 경로를 찾을 수 없습니다
    at java.io.WinNTFileSystem.createFileExclusively(Native Method)
    at java.io.File.createNewFile(Unknown Source)
    at importer.inter.unzip(inter.java:185)
    at importer.inter.unzip(inter.java:158)
    at importer.inter.actionPerformed(inter.java:87)
    at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
    at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
    at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
    at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
    at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
    at java.awt.Component.processMouseEvent(Unknown Source)
    at javax.swing.JComponent.processMouseEvent(Unknown Source)
    at java.awt.Component.processEvent(Unknown Source)
    at java.awt.Container.processEvent(Unknown Source)
    at java.awt.Component.dispatchEventImpl(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
    at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
    at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Window.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$000(Unknown Source)
    at java.awt.EventQueue$1.run(Unknown Source)
    at java.awt.EventQueue$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source)
    at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue$2.run(Unknown Source)
    at java.awt.EventQueue$2.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)
    이렇게 떠요ㅠㅠ 이렇게 되면 어떻게하죠?? ㅠㅠ

    • 폭풍의검
      2012.02.09 11:33

      용량 문제는 아닌것 같습니다.

      압축된 zip폴더안에 폴더가 있으면, 지정된 경로를 찾을수 없다고 뜨네요,

  4. 도와주세요
    2013.05.10 10:11

    한글잔인하게 깨지는데요? ㅠㅠ

  5. 혹시나.
    2014.02.18 21:26

    꽤 시간이 지났지만 지정된 경로를 찾을 수 없다고 뜨시는 분들은
    압축된 파일 안에 폴더가 없는지 확인해보세요.
    압축파일내의 파일을 먼저 찾아가서 압축을 풀고 있는데
    폴더 안에 첫번째 파일이 있으면 지정된 경로를 찾을 수 없다고 뜨네요

    (적어도 저는 그랬어요~ 지나가다 남깁니다~)

  6. HorseKim
    2014.08.18 13:50

    오늘 이 글을 발견해서 이용하다보니 수정본을 받아

    아무리 시도를 해봐도 디렉토리가 없다면서 에러가 나더군요...

    그래서 소스를 천천히 살펴 보던 중 해결책이 떠올라 아래에 남깁니다.



    public void unzip( InputStream is, File destDir, String encoding) throws IOException

    함수 내에

    if ( entry.isDirectory() ){ } else {} 부분 구문이 있는데...

    else 시작부분에
    if(target.getAbsolutePath().lastIndexOf("/") >= 0) {
    String tempFilepath = target.getAbsolutePath().substring(0, target.getAbsolutePath().lastIndexOf("/"));
    File tempFile = new File(tempFilepath);
    if(!tempFile.exists()) {
    tempFile.mkdirs();
    }
    }

    추가해서 해결했습니다.(그냥 즉흥적으로 해결한거라... 더 좋은 방법이 있을수도 있겠음...)

    원인은 zip내부에 압축을 풀려는 대상 파일이 directory안에 있으면
    (ex : aaa.zip 내에 /abc/abc.txt 이런 식...)
    entry.isDirectory()를 false로 내뱉어서 디렉토리가 없어 압축을 풀지 못하더군요...

    • 2014.08.18 22:30 신고

      아.. 그렇군요. 그런 경우는 zip entry를 조회할때 "/aaa" 라는 디렉토리 엔트리가 먼저 나온 후에 그 디렉토리 내의 "/aaa/abc.txt"파일 엔트리가 나오는 경우를 전제로 하고 있었는데 그렇지 않은 경우가 존재하는듯 하네요.

      디렉토리 이전에 파일 엔트리가 먼저 등장할 수 있는지(즉 /aaa/abc.txt 엔트리가 나오고나서 /aaa 에ㅣ트리가 나오는 경우), 아니면 zis.getNextZipEntry() 가 그 순서대로 반환해주지 않는 것인지 확인을 해봐야 할듯 싶습니다.

      제가 테스트 했을때는 항상 디렉토리 엔트리가 먼저 나온 후에 그 디렉토리에 속한 파일 엔트리가 나왔기 때문에 위와 같은 경우는 존재하지 않는다고 생각했거든요.

나의이름 패스워드

홈페이지 비밀글