2 * Copyright (C) 2016 Hiroshi Miura
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.
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.
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.
19 package org.dict.zip.cli;
21 import java.io.EOFException;
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;
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;
47 * Dictionary data handling class.
48 * @author Hiroshi Miura
50 public class DictData {
52 private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
53 .getBundle("org/dict/zip/cli/Bundle", Locale.getDefault());
55 private final Path originalFileName;
56 private final Path compressedFileName;
57 private static final int BUF_LEN = 58315;
60 * Default constructor.
61 * @param originalFilePath to handle
62 * @param compressedFilePath to handle
64 public DictData(@NotNull final Path originalFilePath, @Nullable final Path compressedFilePath) {
65 this.originalFileName = originalFilePath;
66 this.compressedFileName = compressedFilePath;
70 * Default constructor.
71 * @param originalFile to handle
72 * @param compressedFile to handle
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;
79 this.compressedFileName = Paths.get(compressedFile.toURI());
84 * Default constructor for reader.
85 * @param originalFileName to handle
86 * @param compressedFileName to handle
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;
93 this.compressedFileName = Paths.get(compressedFileName);
98 * Print header information to STDOUT.
99 * @throws IOException when stdout is terminated.
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,
122 System.out.printf("%3.1f%%\t%s%n", (100.0 * comp) / uncomp, filename);
128 * @param level indicate compression level from fast to best.
129 * @throws IOException if file I/O error.
131 public void doZip(final CompressionLevel level) throws IOException {
133 byte[] buf = new byte[BUF_LEN];
134 File originalFile = originalFileName.toFile();
136 case BEST_COMPRESSION:
137 defLevel = Deflater.BEST_COMPRESSION;
140 defLevel = Deflater.BEST_SPEED;
142 case DEFAULT_COMPRESSION:
144 defLevel = Deflater.DEFAULT_COMPRESSION;
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)) {
152 while ((len = ins.read(buf, 0, BUF_LEN)) > 0) {
153 dout.write(buf, 0, len);
155 } catch (EOFException eof) {
162 * @param start start offset of data
163 * @param size size to retrieve
164 * @throws IOException if file I/O error.
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];
174 while ((len = din.read(buf, 0, BUF_LEN)) > 0) {
175 unzipOut.write(buf, 0, len);
181 while (size - readSize > 0) {
182 if (size - readSize < BUF_LEN) {
183 len = din.read(buf, 0, size - readSize);
185 len = din.read(buf, 0, BUF_LEN);
188 unzipOut.write(buf, 0, len);
194 } catch (EOFException eof) {