[zip] 압축하기3

프로그래밍/Java 2010. 10. 11. 16:39 Posted by galad
        // 압축 처리
        // 압축대상 폴더명을 압축에서 제외.
        // dirPath = /data/drm
        // zipPath = /data/drm/book
        // 압축 푼 디렉토리 = /data/drm/book
        // book 디렉토리를 대상으로 압축 시, 기본적으로는 book 디렉토리가 포함되어 압축되나
        // sourcePath를 한 depth 안쪽, 즉 zipPath로 지정하면 book 디렉토리를 제외한 상태로 압축된다.
        // (압축 시 압축대상 파일의 절대경로 - sourcePath의 경로)로 파일명 처리하므로, sourcePath를 조정하면 압축대상 디렉토리 제외 가능
        // 기존 압축파일 = book/내에 모든 파일. zipPath를 sourcePath로 하는 압축파일 = /모든 파일
//     zipEntry(dirPath, sourceFile, dirPath, zfileNm);
        zipEntry(zipPath, sourceFile, dirPath, zfileNm);


    /**
     * 압축 대상 파일이나 폴더를 압축 파일에 추가하여 압축한다.
     * 만일 넘겨 받은 파일이 폴더라면 하위 디렉토리 압축을 위해 재귀함수 호출로 처리한다.
     * @param sourcePath 압축할 디렉토리 또는 파일이 위치한 경로. 즉 압축대상의 부모의 경로 / 예) D:\APIs\
     * @param sourceFile 압축할 디렉토리명 또는 이름 / 예) D:\APIs\ 내의 압축대상 j2sdk-1_4_2-doc
     * @param targetDir 압축한 zip 파일을 위치시킬 디렉토리 경로와 이름 / 예) D:\APIs
     * @param zipOutputStream Zip출력스트림 - 압축할 zip 파일에 대한 zip출력스트림. / 예) D:\APIs\zipModuleTest.zip
     * @throws Exception
     */
    private static void zipEntry(String sourcePath,
                                File sourceFile,
                                String targetDir,
                                ZipOutputStream zipOutputStream) throws Exception{

        // 만일 디렉토리명이 .metadata라면 처리하지 않고 skip한다.
        if (sourceFile.isDirectory()) {
            if(sourceFile.getName().equalsIgnoreCase(".metadata")) {
                return;
            }

            File[] fileArray = sourceFile.listFiles();
            for(int i = 0; i < fileArray.length; i++) { // 디렉토리면 디렉토리 내 파일 목록을 가지고 재귀호출
                zipEntry(sourcePath, fileArray[i], targetDir,zipOutputStream);
            }
        } else {
            BufferedInputStream inputStream = null;
            byte[] buffer = new byte[BUFFER_SIZE];
            try {
                if (sourceFile.getAbsolutePath().equalsIgnoreCase(targetDir)) {
                    return;
                }

                String strAbsPath = sourceFile.getPath(); // 압축대상 파일의 절대경로

                // 압축대상 파일의 절대경로에서 원본경로를 제외한 경로를 추출
                // ex) /test/test.xml 에서 test.xml을 압축하면 sourcePath = /test/,
                // 압축대상의 절대경로는 /test/test.xml 이므로 zipEntryName은 test.xml 이 된다.
                // ex2) 만약 디렉토리 내의 파일을 압축하면(디렉토리도 압축에 포함됨), /test/dir/test.xml 에서 dir 을 압축하면
                // sourePath = /test/, 압축대상의 절대경로는 /test/dir/test.xml 이므로 zipEntryName은 dir/test.xml 이 된다.
                // 이 상태로 압축하면 압축파일 내에 dir 디렉토리도 생성됨.
                // sourcePath를 조절해서 압축대상 dir도 제외가능
                String strZipEntryName = strAbsPath.substring(sourcePath.length() + 1, strAbsPath.length());

                inputStream = new BufferedInputStream(new FileInputStream(sourceFile));
                ZipEntry zentry = new ZipEntry(strZipEntryName);
                zentry.setTime(sourceFile.lastModified());
                zipOutputStream.putNextEntry(zentry);

                int cnt =0;
                while ( (cnt = inputStream.read(buffer, 0, BUFFER_SIZE)) != -1) {
                    zipOutputStream.write(buffer, 0, cnt);
                }

                zipOutputStream.closeEntry();
            }
            catch (Exception e) {
                e.printStackTrace();
            }
            finally {
                if (inputStream != null) {
                    inputStream.close();
                }
            }
        }
    }

    /**
     * 압축 대상 파일이나 폴더를 압축 파일에 추가하여 압축한다.
     * @param sourcePath 압축할 디렉토리 또는 파일이 위치한 경로. 즉 압축대상의 부모의 경로 / 예) D:\APIs\
     * @param sourceFile 압축할 디렉토리명 또는 이름 / 예) D:\APIs\ 내의 압축대상 j2sdk-1_4_2-doc
     * @param targetDir 압축한 zip 파일을 위치시킬 디렉토리 경로와 이름 / 예) D:\APIs
     * @param zipFileName zip파일명
     * @throws Exception
     */
    private static void zipEntry(String sourcePath,
                                    File sourceFile,
                                    String targetDir,
                                    String zipFileName) throws Exception {

        // java.util.zip.ZipOutputStream을 사용하면 압축시 한글 파일명은 깨지는 버그가 발생
        // 집출력 스트림에 집파일을 넣는다.
        ZipOutputStream zoutput = new ZipOutputStream((OutputStream) new FileOutputStream(new File(zipFileName)));

        zipEntry(sourcePath, sourceFile, targetDir, zoutput);

        if(zoutput != null)
            zoutput.close();
    }