1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.waarp.compress;
22
23 import com.github.luben.zstd.Zstd;
24 import com.github.luben.zstd.ZstdInputStream;
25 import com.github.luben.zstd.ZstdOutputStream;
26 import com.github.luben.zstd.util.Native;
27 import com.google.common.io.ByteStreams;
28 import org.waarp.common.file.FileUtils;
29 import org.waarp.common.logging.WaarpLogger;
30 import org.waarp.common.logging.WaarpLoggerFactory;
31 import org.waarp.compress.zstdjni.ZstdJniCodec;
32 import org.waarp.compress.zstdsafe.ZstdSafeCodec;
33 import org.waarp.compress.zstdunsafe.UnsafeUtil;
34 import org.waarp.compress.zstdunsafe.ZstdUnsafeCodec;
35
36 import java.io.File;
37 import java.io.FileInputStream;
38 import java.io.FileOutputStream;
39 import java.io.InputStream;
40 import java.io.OutputStream;
41
42
43
44
45
46
47
48
49
50
51
52
53
54 public class WaarpZstdCodec {
55 private static final WaarpLogger logger =
56 WaarpLoggerFactory.getLogger(WaarpZstdCodec.class);
57 private final CompressorCodec codec;
58
59 public WaarpZstdCodec() {
60 boolean jniLoaded;
61 try {
62 Native.load();
63 jniLoaded = true;
64 } catch (final Exception e) {
65 jniLoaded = false;
66 logger.warn("Cannot load JNI based ZSTD codec: {}", e.getMessage());
67 }
68 if (jniLoaded) {
69 codec = new ZstdJniCodec();
70 } else {
71 if (UnsafeUtil.isValid()) {
72 codec = new ZstdUnsafeCodec();
73 } else {
74 codec = new ZstdSafeCodec();
75 }
76 }
77 }
78
79
80
81
82 public final CompressorCodec getCompressorCodec() {
83 return codec;
84 }
85
86
87
88
89
90
91 public static int getMaxCompressedSize(final int bufferSize) {
92 return ZstdSafeCodec.maxCompressedSize(bufferSize);
93 }
94
95
96
97
98
99
100
101
102
103
104
105 public final long compress(final File input, final File output)
106 throws MalformedInputException {
107 InputStream inputStream = null;
108 OutputStream outputStream = null;
109 try {
110 final byte[] buffer;
111 if (codec instanceof ZstdJniCodec) {
112 inputStream = new FileInputStream(input);
113 outputStream = new ZstdOutputStream(new FileOutputStream(output), 1);
114 buffer = new byte[Zstd.blockSizeMax()];
115 while (true) {
116 final int r = inputStream.read(buffer);
117 if (r == -1) {
118 break;
119 }
120 outputStream.write(buffer, 0, r);
121 }
122 } else {
123 inputStream = new FileInputStream(input);
124 buffer = ByteStreams.toByteArray(inputStream);
125 outputStream = new FileOutputStream(output);
126
127 final byte[] bufferCompression =
128 new byte[getMaxCompressedSize(buffer.length)];
129 final int length =
130 codec.compress(buffer, buffer.length, bufferCompression,
131 bufferCompression.length);
132 outputStream.write(bufferCompression, 0, length);
133 }
134 outputStream.flush();
135 FileUtils.close(outputStream);
136 outputStream = null;
137 return output.length();
138 } catch (final Exception e) {
139 throw new MalformedInputException(e);
140 } finally {
141 FileUtils.close(inputStream);
142 FileUtils.close(outputStream);
143 }
144 }
145
146
147
148
149
150
151
152
153
154
155
156 public final long decompress(final File input, final File output)
157 throws MalformedInputException {
158 InputStream inputStream = null;
159 OutputStream outputStream = null;
160 try {
161 final byte[] buffer;
162 if (codec instanceof ZstdJniCodec) {
163 inputStream = new ZstdInputStream(new FileInputStream(input));
164 outputStream = new FileOutputStream(output);
165 buffer = new byte[Zstd.blockSizeMax()];
166 while (true) {
167 final int r = inputStream.read(buffer);
168 if (r == -1) {
169 break;
170 }
171 outputStream.write(buffer, 0, r);
172 }
173 } else {
174 inputStream = new FileInputStream(input);
175 final byte[] sourceArray = ByteStreams.toByteArray(inputStream);
176 outputStream = new FileOutputStream(output);
177
178 buffer = new byte[codec.getDecompressedSize(sourceArray,
179 sourceArray.length)];
180 final int length =
181 codec.decompress(sourceArray, sourceArray.length, buffer,
182 buffer.length);
183 outputStream.write(buffer, 0, length);
184 }
185 outputStream.flush();
186 FileUtils.close(outputStream);
187 outputStream = null;
188 return output.length();
189 } catch (final Exception e) {
190 throw new MalformedInputException(e);
191 } finally {
192 FileUtils.close(inputStream);
193 FileUtils.close(outputStream);
194 }
195 }
196 }