OSDN Git Service

a60a55df50dc4856c90b3b0838f837b93edd0f1c
[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.nio.file.Path;
28 import java.nio.file.Paths;
29 import java.text.Format;
30 import java.text.SimpleDateFormat;
31 import java.util.Date;
32 import java.util.Locale;
33 import java.util.ResourceBundle;
34 import java.util.zip.Deflater;
35
36
37 import org.dict.zip.DictZipHeader.CompressionLevel;
38 import org.dict.zip.DictZipInputStream;
39 import org.dict.zip.DictZipOutputStream;
40 import org.dict.zip.RandomAccessInputStream;
41 import org.dict.zip.RandomAccessOutputStream;
42 import org.jetbrains.annotations.NotNull;
43 import org.jetbrains.annotations.Nullable;
44
45
46 /**
47  * Dictionary data handling class.
48  * @author Hiroshi Miura
49  */
50 public class DictData {
51
52     private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
53             .getBundle("org/dict/zip/cli/Bundle", Locale.getDefault());
54
55     private final Path originalFileName;
56     private final Path compressedFileName;
57     private static final int BUF_LEN = 58315;
58
59     /**
60      * Default constructor.
61      * @param originalFilePath to handle
62      * @param compressedFilePath to handle
63      */
64     public DictData(@NotNull final Path originalFilePath, @Nullable final Path compressedFilePath) {
65         this.originalFileName = originalFilePath;
66         this.compressedFileName = compressedFilePath;
67     }
68
69     /**
70      * Default constructor.
71      * @param originalFile to handle
72      * @param compressedFile to handle
73      */
74     public DictData(@NotNull final File originalFile, @Nullable final File compressedFile) {
75         this.originalFileName = Paths.get(originalFile.toURI());
76         if (compressedFile == null) {
77             this.compressedFileName = null;
78         } else {
79             this.compressedFileName = Paths.get(compressedFile.toURI());
80         }
81     }
82
83     /**
84      * Default constructor for reader.
85      * @param originalFileName to handle
86      * @param compressedFileName to handle
87      */
88     public DictData(@NotNull final String originalFileName, @Nullable final String compressedFileName) {
89         this.originalFileName = Paths.get(originalFileName);
90         if (compressedFileName == null) {
91             this.compressedFileName = null;
92         } else {
93             this.compressedFileName = Paths.get(compressedFileName);
94         }
95     }
96
97     /**
98      * Print header information to STDOUT.
99      * @throws IOException when stdout is terminated.
100      */
101     public void printHeader() throws IOException {
102         File targetFile = originalFileName.toFile();
103         RandomAccessFile targetRaFile = new RandomAccessFile(targetFile, "r");
104         try (RandomAccessInputStream in = new RandomAccessInputStream(targetRaFile);
105              DictZipInputStream din = new DictZipInputStream(in);) {
106             // These three parameters are able to get only from din.
107             long uncomp = din.getLength();
108             long comp = din.getCompLength();
109             long crc = din.getCrc();
110             // Get header parameters.
111             String type = din.getType();
112             int chunkLength = din.getChunkLength();
113             int chunkCount = din.getChunkCount();
114             Date mtime = new Date(din.getMtime() * 1000);
115             String filename = din.getFilename();
116             Format timeFormatter = new SimpleDateFormat("MMMM dd, yyyy hh:mm:ss");
117             System.out.println(RESOURCE_BUNDLE.getString("dictzip.header.title"));
118             System.out.printf("%s\t%08x\t%s\t", type, crc,
119                     timeFormatter.format(mtime));
120             System.out.printf("%6d\t%d\t%d\t  %d\t", chunkCount, chunkLength, comp,
121                     uncomp);
122             System.out.printf("%3.1f%%\t%s%n", (100.0 * comp) / uncomp, filename);
123         }
124     }
125
126     /**
127      * Do compression.
128      * @param level indicate compression level from fast to best.
129      * @throws IOException if file I/O error.
130      */
131     public void doZip(final CompressionLevel level) throws IOException {
132         int defLevel;
133         byte[] buf = new byte[BUF_LEN];
134         File originalFile = originalFileName.toFile();
135         switch (level) {
136             case BEST_COMPRESSION:
137                 defLevel = Deflater.BEST_COMPRESSION;
138                 break;
139             case BEST_SPEED:
140                 defLevel = Deflater.BEST_SPEED;
141                 break;
142             case DEFAULT_COMPRESSION:
143             default:
144                 defLevel = Deflater.DEFAULT_COMPRESSION;
145                 break;
146         }
147         try (FileInputStream ins = new FileInputStream(originalFile);
148              DictZipOutputStream dout = new DictZipOutputStream(
149                     new RandomAccessOutputStream(new RandomAccessFile(compressedFileName.toFile(), "rws")),
150                      BUF_LEN, originalFile.length(), defLevel)) {
151             int len;
152             while ((len = ins.read(buf, 0, BUF_LEN)) > 0) {
153                 dout.write(buf, 0, len);
154             }
155         } catch (EOFException eof) {
156                 // ignore it.
157         }
158     }
159
160     /**
161      * Do uncompression.
162      * @param start start offset of data
163      * @param size size to retrieve
164      * @throws IOException if file I/O error.
165      */
166     public void doUnzip(final long start, final int size) throws IOException {
167         try (DictZipInputStream din = new DictZipInputStream(new RandomAccessInputStream(new
168                         RandomAccessFile(compressedFileName.toFile(), "r")));
169                 OutputStream unzipOut = new RandomAccessOutputStream(originalFileName.toAbsolutePath().toString(), "rw")) {
170             byte[] buf = new byte[BUF_LEN];
171             din.seek(start);
172             if (size == 0) {
173                 int len;
174                 while ((len = din.read(buf, 0, BUF_LEN)) > 0) {
175                     unzipOut.write(buf, 0, len);
176                 }
177             } else {
178                 try {
179                     int len;
180                     int readSize = 0;
181                     while (size - readSize > 0) {
182                         if (size - readSize < BUF_LEN) {
183                             len = din.read(buf, 0, size - readSize);
184                         } else {
185                             len = din.read(buf, 0, BUF_LEN);
186                         }
187                         if (len > 0) {
188                             unzipOut.write(buf, 0, len);
189                             readSize += len;
190                         } else {
191                             break;
192                         }
193                     }
194                 } catch (EOFException eof) {
195                     // ignore it.
196                 }
197             }
198         }
199     }
200
201 }