4 * Copyright (C) 2016-2022 Hiroshi Miura
6 * SPDX-License-Identifier: GNU General Public License v2.0 or later
9 package org.dict.zip.cli;
11 import org.dict.zip.DictZipHeader.CompressionLevel;
12 import org.dict.zip.DictZipInputStream;
13 import org.dict.zip.DictZipOutputStream;
14 import org.dict.zip.RandomAccessInputStream;
15 import org.dict.zip.RandomAccessOutputStream;
16 import org.jetbrains.annotations.NotNull;
17 import org.jetbrains.annotations.Nullable;
19 import java.io.EOFException;
21 import java.io.FileInputStream;
22 import java.io.IOException;
23 import java.io.OutputStream;
24 import java.io.RandomAccessFile;
25 import java.nio.file.Path;
26 import java.nio.file.Paths;
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;
36 * Dictionary data handling class.
37 * @author Hiroshi Miura
39 public class DictData {
41 private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
42 .getBundle("org/dict/zip/cli/Bundle", Locale.getDefault());
44 private final Path originalFileName;
45 private final Path compressedFileName;
46 private static final int BUF_LEN = 58315;
49 * Default constructor.
50 * @param originalFilePath to handle
51 * @param compressedFilePath to handle
53 public DictData(@NotNull final Path originalFilePath, @Nullable final Path compressedFilePath) {
54 this.originalFileName = originalFilePath;
55 this.compressedFileName = compressedFilePath;
59 * Default constructor.
60 * @param originalFile to handle
61 * @param compressedFile to handle
63 public DictData(@NotNull final File originalFile, @Nullable final File compressedFile) {
64 this.originalFileName = Paths.get(originalFile.toURI());
65 if (compressedFile == null) {
66 this.compressedFileName = null;
68 this.compressedFileName = Paths.get(compressedFile.toURI());
73 * Default constructor for reader.
74 * @param originalFileName to handle
75 * @param compressedFileName to handle
77 public DictData(@NotNull final String originalFileName, @Nullable final String compressedFileName) {
78 this.originalFileName = Paths.get(originalFileName);
79 if (compressedFileName == null) {
80 this.compressedFileName = null;
82 this.compressedFileName = Paths.get(compressedFileName);
87 * Print header information to STDOUT.
88 * @throws IOException when stdout is terminated.
90 public void printHeader() throws IOException {
91 File targetFile = originalFileName.toFile();
92 RandomAccessFile targetRaFile = new RandomAccessFile(targetFile, "r");
93 try (RandomAccessInputStream in = new RandomAccessInputStream(targetRaFile);
94 DictZipInputStream din = new DictZipInputStream(in)) {
95 // These three parameters are able to get only from din.
96 long uncomp = din.getLength();
97 long comp = din.getCompLength();
98 long crc = din.getCrc();
99 // Get header parameters.
100 String type = din.getType();
101 int chunkLength = din.getChunkLength();
102 int chunkCount = din.getChunkCount();
103 Date mtime = new Date(din.getMtime() * 1000);
104 String filename = din.getFilename();
105 Format timeFormatter = new SimpleDateFormat("MMMM dd, yyyy hh:mm:ss");
106 System.out.println(RESOURCE_BUNDLE.getString("dictzip.header.title"));
107 System.out.printf("%s\t%08x\t%s\t", type, crc,
108 timeFormatter.format(mtime));
109 System.out.printf("%6d\t%d\t%d\t %d\t", chunkCount, chunkLength, comp,
111 System.out.printf("%3.1f%%\t%s%n", (100.0 * comp) / uncomp, filename);
117 * @param level indicate compression level from fast to best.
118 * @throws IOException if file I/O error.
120 public void doZip(final CompressionLevel level) throws IOException {
122 byte[] buf = new byte[BUF_LEN];
123 File originalFile = originalFileName.toFile();
125 case BEST_COMPRESSION:
126 defLevel = Deflater.BEST_COMPRESSION;
129 defLevel = Deflater.BEST_SPEED;
131 case DEFAULT_COMPRESSION:
133 defLevel = Deflater.DEFAULT_COMPRESSION;
136 try (FileInputStream ins = new FileInputStream(originalFile);
137 DictZipOutputStream dout = new DictZipOutputStream(
138 new RandomAccessOutputStream(new RandomAccessFile(compressedFileName.toFile(), "rws")),
139 BUF_LEN, originalFile.length(), defLevel)) {
141 while ((len = ins.read(buf, 0, BUF_LEN)) > 0) {
142 dout.write(buf, 0, len);
144 } catch (EOFException eof) {
151 * @param start start offset of data
152 * @param size size to retrieve
153 * @throws IOException if file I/O error.
155 public void doUnzip(final long start, final int size) throws IOException {
156 try (DictZipInputStream din = new DictZipInputStream(new RandomAccessInputStream(new
157 RandomAccessFile(compressedFileName.toFile(), "r")));
158 OutputStream unzipOut = new RandomAccessOutputStream(originalFileName.toAbsolutePath().toString(), "rw")) {
159 byte[] buf = new byte[BUF_LEN];
163 while ((len = din.read(buf, 0, BUF_LEN)) > 0) {
164 unzipOut.write(buf, 0, len);
170 while (size - readSize > 0) {
171 if (size - readSize < BUF_LEN) {
172 len = din.read(buf, 0, size - readSize);
174 len = din.read(buf, 0, BUF_LEN);
177 unzipOut.write(buf, 0, len);
183 } catch (EOFException eof) {