친구가 압축된 파일을 풀면서 한라인씩 데이터를 가져와 처리하는게 궁금하다길래 나도 궁금하여 찾아본 내용.
압축 방식에 따른 알고리즘을 제대로 알아야 맞지만 허프만 알고리즘만 좀 알면 찾을 필욘 없겠지요.
대신 서핑하다 알게된 건데 java API엔 gzip과 zip을 압축/해제 할 수 있는 API가 제공되고 있었습니다.
jar를 쓰니 당연하겠네요. 그 것에 대해 한번 돌려본 내용입니다.


테스트한 코드는 다음과 같습니다.
import java.io.*;
import java.util.zip.*;

public class Gzip {

    final static String decompressedFile = "c:/testFile.txt";
    final static String decompressedFile2 = "c:/testFile2.txt";
    final static String compressedFile = "c:/testFile.txt.gz";
   
    public static void main(String[] args) {
        Gzip test = new Gzip();
        try {
            System.out.println("start compress ...");
            test.compress();

            System.out.println("start decompress ...");
            test.decompress();
           
            System.out.println("complete compress/decompress process");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void compress() throws IOException {

        long startTime = startTime = System.currentTimeMillis();
       
        BufferedReader in = new BufferedReader(new FileReader(decompressedFile));
        BufferedOutputStream out = new BufferedOutputStream(
                new GZIPOutputStream(new FileOutputStream(compressedFile)));

        String s;
        while (null != (s = in.readLine())) {
            out.write(s.getBytes());
            out.write("\n".getBytes());
        }
        in.close();
        out.close();
       
        long endTime = System.currentTimeMillis();
        System.out.println("compress elapsed time : " + (endTime - startTime) + " ms");
    }
   
    public void decompress() throws FileNotFoundException, IOException, InterruptedException {

        long startTime = System.currentTimeMillis();
        BufferedReader in = new BufferedReader(
                new InputStreamReader(new GZIPInputStream(new FileInputStream(compressedFile))));
        BufferedOutputStream out = new BufferedOutputStream(
                new FileOutputStream(decompressedFile2));
       
        String s;
        while (null != (s = in.readLine())) {
            out.write(s.getBytes());
            out.write("\n".getBytes());
        }
        in.close();
        out.close();
       
        long endTime = System.currentTimeMillis();
        System.out.println("decompress elapsed time : " + (endTime - startTime) + " ms");
       
    }
}

java.util.zip 패키지의 GZIPOutputStream, GZIPInputStream 쓴고 while 문에서 라인별로 읽고 씁니다.
compress() 에서 데이터파일을 읽어서 압축하고 시간 체크,
decompress() 에서 압축파일을 읽어서 다시 일반 Text 파일로 씁니다.
테스트에 사용한 testFile.txt는 1GB의 텍스트 데이터로 11189999 라인정도 됩니다.

시간체크를 했는데
     compress()의 경우 100~110초 정도 나오고
     decompress()의 경우 89~100초 정도 나옵니다.
만약 decompress()에서 파일로 쓰는 작업을 빼면 속도가 2배정도 빨라지네요. (40초 정도 나왔습니다.)

결국 대용량 파일 배치 작업의 경우 몇시간에서 몇십시간씩 돌기 때문에
     저정도의 시간희생은 별 문제가 안되고
     용량에 대한 이점이 더 크기 때문에
압축해서 데이터를 사용하는 것 같습니다.

실제 테스트한 파일인
    testFile.txt는 1,049,140 kb 이며
    압축시 testFile.txt.gz 30,835 KB로
압축됩니다.  (1GB -> 30MB)

참조자료
  Compress data streams with GZIP and Zip :
  http://www.zdnetasia.com/techguide/java/0,39044898,62038041,00.htm 

  Basic Compression Library :
  http://bcl.comli.eu/

  Compressing and Decompressing Data Using Java APIs :
  http://java.sun.com/developer/technicalArticles/Programming/compression/

  7zip
  http://7-zip.org/

7zip 같은 경우는 open source 압축 프로그램이기 때문에 소스가 공개되어있습니다. 대부분 c/c++ 입니다.



다음은 테스트에 사용한 testFile.txt 생성한 소스입니다. 이것저것 다 올리기..
import java.io.*;

public class CreateSampleFile {
    final static String str = ":날 위해 감춰왔던 아픔이 보여요 You and I together it's just feel alright";   
    public static void main(String[] args) {
        BufferedWriter out = null;
        String fileName = "c:/testFile.txt";
        File file = new File(fileName);       
        try {
            out = new BufferedWriter(new FileWriter(fileName));           
            long lineNum = 1;
            while ( true ) {
                out.write((lineNum++) + str); out.newLine();
                if (0 == lineNum %10000) { // byte 단위 - 1GB보다 크다면
                    if (file.length() > 1073741824L ) break;
                }
            }           
        } catch (IOException e) { e.printStackTrace(); } finally {
            try { if ( null != out) out.close(); } catch (IOException e) { e.printStackTrace(); }
        }
    }
}



음 근대 원본 파일이랑 압축한후 해제한 파일이 용량이 틀린 현상이 생겼습니다. 뭘까요.
잘 모르겠지만 캐리지 리턴 문자를 잘못쓴게 아닐까 합니다. 그냥 패쓰...


'Java' 카테고리의 다른 글

[spring boot] websocket 예제 중 html 부분  (0) 2017.10.18
클라이언트/서버 심플  (0) 2012.06.21
Thread 기본, IO, NIO 기본 내용들  (0) 2011.01.03
Java에서 XML 다루기 DOM, SAX, JDOM, StAX  (3) 2010.02.06
Java Thread  (0) 2010.01.24
Exception 을 문자열로...  (0) 2009.09.07
Java Compile 사용  (0) 2009.08.26
Java에서 외부 프로그램 실행  (0) 2009.08.26