OSDN Git Service

CLI: Implement compression level option
[dictzip-java/dictzip-java.git] / dictzip-cli / src / main / java / org / dict / zip / cli / DictData.java
1 /*
2  * Copyright (C) 2016 Hiroshi Miura
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17  */
18
19 package org.dict.zip.cli;
20
21 import java.io.EOFException;
22 import java.io.File;
23 import java.io.FileInputStream;
24 import java.io.IOException;
25 import java.io.OutputStream;
26 import java.io.RandomAccessFile;
27 import java.text.Format;
28 import java.text.SimpleDateFormat;
29 import java.util.Date;
30 import java.util.Locale;
31 import java.util.ResourceBundle;
32 import java.util.zip.Deflater;
33
34
35 import org.dict.zip.DictZipHeader;
36 import org.dict.zip.DictZipHeader.CompressionLevel;
37 import org.dict.zip.DictZipInputStream;
38 import org.dict.zip.DictZipOutputStream;
39 import org.dict.zip.RandomAccessInputStream;
40 import org.dict.zip.RandomAccessOutputStream;
41
42
43 /**
44  * Dictionary data handling class.
45  * @author Hiroshi Miura
46  */
47 public class DictData {
48
49     private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
50             .getBundle("org/dict/zip/cli/Bundle", Locale.getDefault());
51
52     private final String originalFileName;
53     private final String compressedFileName;
54     private static final int BUF_LEN = 58315;
55
56     /**
57      * Default constructor for reader.
58      * @param originalFileName to handle
59      * @param compressedFileName to handle
60      */
61     public DictData(final String originalFileName, final String compressedFileName) {
62         this.originalFileName = originalFileName;
63         this.compressedFileName = compressedFileName;
64     }
65
66     /**
67      * Print header information to STDOUT.
68      * @throws IOException when stdout is terminated.
69      */
70     public void printHeader() throws IOException {
71         File targetFile = new File(originalFileName);
72         RandomAccessFile targetRaFile = new RandomAccessFile(targetFile, "r");
73         try (RandomAccessInputStream in = new RandomAccessInputStream(targetRaFile);
74              DictZipInputStream din = new DictZipInputStream(in);) {
75             long uncomp = din.getLength();
76             long comp = din.getCompLength();
77             long crc = din.getCrc();
78             DictZipHeader header = din.readHeader();
79             String type = header.getType();
80             int chunkLength = header.getChunkLength();
81             int chunkCount = header.getChunkCount();
82             Date mtime = new Date(header.getMtime() * 1000);
83             String filename = header.getFilename();
84             Format timeFormatter = new SimpleDateFormat("MMMM dd, yyyy hh:mm:ss");
85             System.out.println(RESOURCE_BUNDLE.getString("dictzip.header.title"));
86             System.out.print(String.format("%s\t%08x\t%s\t", type, crc,
87                     timeFormatter.format(mtime)));
88             System.out.print(String.format("%6d\t%d\t%d\t  %d\t", chunkCount, chunkLength, comp,
89                     uncomp));
90             System.out.println(String.format("%3.1f%%\t%s", (100.0 * comp) / uncomp, filename));
91         } catch (RuntimeException ex) {
92             throw ex;
93         }
94     }
95
96     /**
97      * Do compression.
98      * @throws IOException if file I/O error.
99      * @param level
100      */
101     public void doZip(CompressionLevel level) throws IOException {
102         int defLevel;
103         byte[] buf = new byte[BUF_LEN];
104         File originalFile = new File(originalFileName);
105         switch (level) {
106             case BEST_COMPRESSION:
107                 defLevel = Deflater.BEST_COMPRESSION;
108                 break;
109             case BEST_SPEED:
110                 defLevel = Deflater.BEST_SPEED;
111                 break;
112             case DEFAULT_COMPRESSION:
113             default:
114                 defLevel = Deflater.DEFAULT_COMPRESSION;
115                 break;
116         }
117         try (FileInputStream ins = new FileInputStream(originalFile);
118              DictZipOutputStream dout = new DictZipOutputStream(
119                     new RandomAccessOutputStream(new RandomAccessFile(compressedFileName, "rws")),
120                      BUF_LEN, originalFile.length(), defLevel)) {
121             int len;
122             while ((len = ins.read(buf, 0, BUF_LEN)) > 0) {
123                 dout.write(buf, 0, len);
124             }
125         } catch (EOFException eof) {
126                 // ignore it.
127         }
128     }
129
130     /**
131      * Do uncompression.
132      * @param start start offset of data
133      * @param size size to retrieve
134      * @throws IOException if file I/O error.
135      */
136     public void doUnzip(final long start, final int size) throws IOException {
137         try (DictZipInputStream din = new DictZipInputStream(new RandomAccessInputStream(new
138                         RandomAccessFile(new File(compressedFileName), "r")));
139                 OutputStream unzipOut = new RandomAccessOutputStream(originalFileName, "rw")) {
140             byte[] buf = new byte[BUF_LEN];
141             din.seek(start);
142             if (size == 0) {
143                 int len;
144                 while ((len = din.read(buf, 0, BUF_LEN)) > 0) {
145                     unzipOut.write(buf, 0, len);
146                 }
147             } else {
148                 try {
149                     int len;
150                     int readSize = 0;
151                     while (size - readSize > 0) {
152                         if (size - readSize < BUF_LEN) {
153                             len = din.read(buf, 0, size - readSize);
154                         } else {
155                             len = din.read(buf, 0, BUF_LEN);
156                         }
157                         if (len > 0) {
158                             unzipOut.write(buf, 0, len);
159                             readSize += len;
160                         } else {
161                             break;
162                         }
163                     }
164                 } catch (EOFException eof) {
165                     // ignore it.
166                 }
167             }
168         }
169     }
170
171 }