[JAVA] 자바에서 만든 zip 파일이 맥(Mac)에서 내부 파일명 한글깨짐/한글 깨지는 경우
자바에서 만든 zip 파일을 맥(Mac)에서 압축해제 시 내부 파일명 한글깨짐/한글 깨지는 경우다.
zip 파일명 자체는 깨지지 않는데, zip 내부 파일들의 파일명이 깨지는 경우다.
처음에는 zip 파일 다운로드하는 과정에 문제가 있다고 생각했는데, zip 압축파일을 만들어내는 방식의 문제였다.
이것은 zip 파일을 압축할 때 파일명을 유니코드(UTF-8)로 저장하는 방식을 사용해서 해결할 수 있다.
그런데 윈도우의 몇몇 압축 프로그램의 경우에는 오히려 파일명을 유니코드(UTF-8)로 해서 압축했을 때 이름이 깨지는 경우도 있다고 하니까, 맥 OS를 사용하는 경우에 대해서만 처리를 해주는 것을 권장한다.
방법은 자바에서 zip 압축파일을 만들 때 ZipOutputStream 객체(import org.apache.tools.zip.ZipOutputStream;) 가 아닌, ZipArchiveOutputStream 객체(import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;) 를 사용하면 된다.
기존 코드에서 ZipOutputStream 객체를 사용하고 있다면 해당 객체만 ZipArchiveOutputStream 객체로 바꿔서 테스트해보자.
ZipArchiveOutputStream 객체를 사용하기 위해서는 Apache Common Compress 라이브러리를 임포트하면 된다.
http://commons.apache.org/compress/ 에서 구할 수 있고, https://mvnrepository.com/artifact/org.apache.commons/commons-compress/1.20 에서도 곧바로 다운로드받을 수 있다.
필자는 1.20 버전을 사용했다. (commons-compress-1.20.jar)
이때 자바 압축 코드의 핵심은 파일명을 UTF-8 인코딩 설정하는 아래 코드이다.
|
zipOutputStream = new ZipArchiveOutputStream(fileOutputStream);
// Mac OS 사용하는 경우 zip 압축파일 내부 파일명 깨지는 문제 방지 zipOutputStream.setEncoding(“UTF-8”); zipOutputStream.setFallbackToUTF8(true); zipOutputStream.setUseLanguageEncodingFlag(true); zipOutputStream.setCreateUnicodeExtraFields(ZipArchiveOutputStream.UnicodeExtraFieldPolicy.ALWAYS);
|
전체적인 코드 수정은 아래와 같이 하면 된다.
[AS-IS]
|
public static void makeZip() { File outputFile = null; FileOutputStream fileOutputStream = null; ZipOutputStream zipOutputStream = null; try { outputFile = new File(“C:\\test\\output.zip”); fileOutputStream = new FileOutputStream(outputFile); zipOutputStream = new ZipOutputStream(fileOutputStream); zipOutputStream.setEncoding(“KSC5601”); ZipEntry zipEntry = new ZipEntry(“input.txt”); zipOutputStream.putNextEntry(zipEntry); FileInputStream fileInputStream = null; try { byte[] buf = new byte[4096]; int byteRead = 0; File inputFile = new File(“C:\\test\\테스트.txt”); fileInputStream = new FileInputStream(inputFile); while ((byteRead = fileInputStream.read(buf)) > 0) { zipOutputStream.write(buf, 0, byteRead); } zipOutputStream.flush(); zipOutputStream.closeEntry(); } catch (Exception e) { throw e; } finally { try { if (fileInputStream != null) { fileInputStream.close(); } } catch (Exception e) {} } } catch (Exception e) { e.printStackTrace(); } finally { try { if (zipOutputStream != null) { zipOutputStream.close(); } } catch (Exception e) {} try { if (fileOutputStream != null) { fileOutputStream.close(); } } catch (Exception e) {} } }
|
[TO-BE]
|
public static void makeZip() { File outputFile = null; FileOutputStream fileOutputStream = null; ZipArchiveOutputStream zipOutputStream = null; try { outputFile = new File(“C:\\test\\output.zip”); fileOutputStream = new FileOutputStream(outputFile); zipOutputStream = new ZipArchiveOutputStream(fileOutputStream);
// Mac OS 사용하는 경우 zip 압축파일 내부 파일명 깨지는 문제 방지 zipOutputStream.setEncoding(“UTF-8”); zipOutputStream.setFallbackToUTF8(true); zipOutputStream.setUseLanguageEncodingFlag(true); zipOutputStream.setCreateUnicodeExtraFields(ZipArchiveOutputStream.UnicodeExtraFieldPolicy.ALWAYS); ZipArchiveEntry zipEntry = new ZipArchiveEntry(“input.txt”); zipOutputStream.putArchiveEntry(zipEntry); FileInputStream fileInputStream = null; try { byte[] buf = new byte[4096]; int byteRead = 0; File inputFile = new File(“C:\\test\\테스트.txt”); fileInputStream = new FileInputStream(inputFile); while ((byteRead = fileInputStream.read(buf)) > 0) { zipOutputStream.write(buf, 0, byteRead); } zipOutputStream.flush(); zipOutputStream.closeArchiveEntry(); } catch (Exception e) { throw e; } finally { try { if (fileInputStream != null) { fileInputStream.close(); } } catch (Exception e) {} } } catch (Exception e) { e.printStackTrace(); } finally { try { if (zipOutputStream != null) { zipOutputStream.close(); } } catch (Exception e) {} try { if (fileOutputStream != null) { fileOutputStream.close(); } } catch (Exception e) {} } }
|
참고사이트 1 : https://visu4l.tistory.com/394
참고사이트 3 : https://huskdoll.tistory.com/m/189?category=526538