파일을 처리하는 애플리케이션을 개발하면서 많은 경우에 파일 처리는 확장자를 기준으로 파일의 타입을 결정하고 처리하게 된다. 예를 들면, 확장자가 .docx 이면 마이크로소프트 워드 파일이라는 것을 알 수 있고, 이 파일의 타입에 적합하게 처리(오픈 등)한다. 이 블로그의 파일 타입별 확장자 분류.. 포스팅을 확인해 보면, 비교적 자주 사용되는 파일 확장자와 그 확장자를 가지고 있는 파일이 어떤 타입의 파일인지 확인할 수 있다.
파일의 포맷을 인식하는 기본 방법이 확장자를 기준으로 타입을 구분해서 처리하는 방법이지만, 종종 파일의 타입을 알 수 없는 경우가 발생한다. 이런 경우는 다음과 같다.
– 수동으로 파일의 확장자를 수정한다.
– 특정 폴더에 이미지의 썸네일을 확장자 없이 저장(안드로이드에서 종종 볼 수 있다)한다.
– 각종 다운로드로 인해서 발생한다.
일반적으로 위 경우에는 파일을 처리하지 못하거나, 제대로 열 수 없는 애플리케이션을 호출하게 된다. 따라서 좀 더 정확하게 파일을 처리하기 위해서는 파일의 헤더를 분석해서 파일의 타입을 확인하고, 그 타입에 맞는 처리가 필요하다. 그래서, 이 글에서는 자바로 파일의 타입을 정확하게 확인할 수 있는 라이브러리를 확인해 보겠다.
파일의 타입을 확인할 수 있는 자바 라이브러리를 찾아보면 아래의 목록을 확인할 수 있다. 그리고 이 라이브러리는 안드로이드에서도 사용할 수 있다.
- SimpleMagic
- Java Mime Magic Library
- https://github.com/arimus/jmimemagic
- 의존 : Apache Common Logging 라이브러리
- Apache Tika
- http://tika.apache.org/
- 의존 : 많음
이 글에서는 Apache Tika는 제외하고, 1.번과 2.번의 라이브러리를 확인해 보겠다. Apache Tika를 제외한 이유는 의존하는 라이브러리가 너무 많아서이다. 대상은 아래에 있는 5개 타입에 대해서 확인해 봤다.
docx = new java.io.File(".").getCanonicalPath() + "/files/docx_file"; jpg = new java.io.File(".").getCanonicalPath() + "/files/jpg_file"; odt = new java.io.File(".").getCanonicalPath() + "/files/open_office_odt_file"; pdf = new java.io.File(".").getCanonicalPath() + "/files/pdf_file"; exe = new java.io.File(".").getCanonicalPath() + "/files/prgrep_exe_file";
위에서 파일의 확장자를 수동으로 변경했고, 이 파일에 대해서 포맷을 정확하게 인식하는 것을 테스트 했고, 결과는 다음과 같다.
– SimpleMagic 결과
0 ContentType : word 0 MimeType : application/vnd.openxmlformats-officedocument.wordprocessingml.document 0 File Extension 0 : docx 1 ContentType : jpeg 1 MimeType : image/jpeg 1 File Extension 0 : jpeg 1 File Extension 1 : jpg 1 File Extension 2 : jpe 2 ContentType : opendocument-text 2 MimeType : application/vnd.oasis.opendocument.text 2 File Extension 0 : odt 3 ContentType : pdf 3 MimeType : application/pdf 3 File Extension 0 : pdf 4 Unknown content-type
– Java Mime Magic Library 결과
0 File Ext : zip 0 File Mimetype : application/zip 1 File Ext : jpg 1 File Mimetype : image/jpeg 2 File Ext : zip 2 File Mimetype : application/zip 3 File Ext : pdf 3 File Mimetype : application/pdf 4 File Ext : ??? 4 File Mimetype : ???
위 개별 라이브러리의 파일 타입 인식 결과로, 자바를 사용해서 파일의 포맷을 더 정확하게 확인하고 사용하려면, SimpleMagic 라이브러를 사용해서 파일의 타입을 확인하는게 좋겠다. 이 테스트를 위해서 사용한 소스는 다음과 같다.
import java.io.File; import java.io.IOException; import net.sf.jmimemagic.Magic; import net.sf.jmimemagic.MagicMatch; import com.j256.simplemagic.ContentInfo; import com.j256.simplemagic.ContentInfoUtil; public class FileFormatCheckTest { static String[] files = null; static String docx = ""; static String jpg = ""; static String odt = ""; static String pdf = ""; static String exe = ""; static { try { docx = new java.io.File(".").getCanonicalPath() + "/files/docx_file"; jpg = new java.io.File(".").getCanonicalPath() + "/files/jpg_file"; odt = new java.io.File(".").getCanonicalPath() + "/files/open_office_odt_file"; pdf = new java.io.File(".").getCanonicalPath() + "/files/pdf_file"; exe = new java.io.File(".").getCanonicalPath() + "/files/prgrep_exe_file"; files = new String[] { docx, jpg, odt, pdf, exe }; } catch (IOException e) { e.printStackTrace(); } } public static void testA() { ContentInfoUtil util = new ContentInfoUtil(); try { ContentInfo info; for (int i = 0; i < files.length; i++) { info = util.findMatch(files[i]); if (info == null) { System.out.println(i + " Unknown content-type"); continue; } System.out.println(i + " ContentType : " + info.getName()); System.out.println(i + " MimeType : " + info.getMimeType()); String[] extensions = info.getFileExtensions(); if (extensions != null && extensions.length > 0) { for (int j = 0; j < extensions.length; j++) { System.out.println(i + " File Extension " + j + " : " + extensions[j]); } } } } catch (IOException e) { e.printStackTrace(); } } public static void testB() { MagicMatch match = null; try { for (int i = 0; i < files.length; i++) { match = Magic.getMagicMatch(new File(files[i]), true, false); if (match != null) { System.out.println(i + " File Ext " + " : " + match.getExtension()); System.out.println(i + " File Mimetype " + " : " + match.getMimeType()); } } } catch (Exception e) { e.printStackTrace(); } } public static void main(String[] args) { // testA(); testB(); } }
프로젝트 다운로드 : FileFormatCheckTest.zip