OSDN Git Service

Release v0.14.1
[dictzip-java/dictzip-java.git] / dictzip-cli / src / main / java / org / dict / zip / cli / DictData.java
1 /*
2  * DictZip library.
3  *
4  * Copyright (C) 2016-2022 Hiroshi Miura
5  *
6  * SPDX-License-Identifier: GNU General Public License v2.0 or later
7  */
8
9 package org.dict.zip.cli;
10
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;
18
19 import java.io.EOFException;
20 import java.io.File;
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;
33
34
35 /**
36  * Dictionary data handling class.
37  * @author Hiroshi Miura
38  */
39 public class DictData {
40
41     private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
42             .getBundle("org/dict/zip/cli/Bundle", Locale.getDefault());
43
44     private final Path originalFileName;
45     private final Path compressedFileName;
46     private static final int BUF_LEN = 58315;
47
48     /**
49      * Default constructor.
50      * @param originalFilePath to handle
51      * @param compressedFilePath to handle
52      */
53     public DictData(@NotNull final Path originalFilePath, @Nullable final Path compressedFilePath) {
54         this.originalFileName = originalFilePath;
55         this.compressedFileName = compressedFilePath;
56     }
57
58     /**
59      * Default constructor.
60      * @param originalFile to handle
61      * @param compressedFile to handle
62      */
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;
67         } else {
68             this.compressedFileName = Paths.get(compressedFile.toURI());
69         }
70     }
71
72     /**
73      * Default constructor for reader.
74      * @param originalFileName to handle
75      * @param compressedFileName to handle
76      */
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;
81         } else {
82             this.compressedFileName = Paths.get(compressedFileName);
83         }
84     }
85
86     /**
87      * Print header information to STDOUT.
88      * @throws IOException when stdout is terminated.
89      */
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,
110                     uncomp);
111             System.out.printf("%3.1f%%\t%s%n", (100.0 * comp) / uncomp, filename);
112         }
113     }
114
115     /**
116      * Do compression.
117      * @param level indicate compression level from fast to best.
118      * @throws IOException if file I/O error.
119      */
120     public void doZip(final CompressionLevel level) throws IOException {
121         int defLevel;
122         byte[] buf = new byte[BUF_LEN];
123         File originalFile = originalFileName.toFile();
124         switch (level) {
125             case BEST_COMPRESSION:
126                 defLevel = Deflater.BEST_COMPRESSION;
127                 break;
128             case BEST_SPEED:
129                 defLevel = Deflater.BEST_SPEED;
130                 break;
131             case DEFAULT_COMPRESSION:
132             default:
133                 defLevel = Deflater.DEFAULT_COMPRESSION;
134                 break;
135         }
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)) {
140             int len;
141             while ((len = ins.read(buf, 0, BUF_LEN)) > 0) {
142                 dout.write(buf, 0, len);
143             }
144         } catch (EOFException eof) {
145                 // ignore it.
146         }
147     }
148
149     /**
150      * Do uncompression.
151      * @param start start offset of data
152      * @param size size to retrieve
153      * @throws IOException if file I/O error.
154      */
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];
160             din.seek(start);
161             if (size == 0) {
162                 int len;
163                 while ((len = din.read(buf, 0, BUF_LEN)) > 0) {
164                     unzipOut.write(buf, 0, len);
165                 }
166             } else {
167                 try {
168                     int len;
169                     int readSize = 0;
170                     while (size - readSize > 0) {
171                         if (size - readSize < BUF_LEN) {
172                             len = din.read(buf, 0, size - readSize);
173                         } else {
174                             len = din.read(buf, 0, BUF_LEN);
175                         }
176                         if (len > 0) {
177                             unzipOut.write(buf, 0, len);
178                             readSize += len;
179                         } else {
180                             break;
181                         }
182                     }
183                 } catch (EOFException eof) {
184                     // ignore it.
185                 }
186             }
187         }
188     }
189
190 }