Update catfile.py
[PyCatFile.git] / compression.py
blob8a0a87d751a5cd97a666ebf0e323c4fa367e44e7
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
4 '''
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the Revised BSD License.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 Revised BSD License for more details.
13 Copyright 2018-2024 Cool Dude 2k - http://idb.berlios.de/
14 Copyright 2018-2024 Game Maker 2k - http://intdb.sourceforge.net/
15 Copyright 2018-2024 Kazuki Przyborowski - https://github.com/KazukiPrzyborowski
17 $FileInfo: compression.py - Last Update: 5/5/2024 Ver. 0.10.2 RC 1 - Author: cooldude2k $
18 '''
20 from __future__ import absolute_import, division, print_function, unicode_literals;
21 import os, binascii, argparse, shutil;
22 from io import open as open;
24 def CompressionSupport():
25 compression_list = [];
26 try:
27 import gzip;
28 compression_list.append("gz");
29 compression_list.append("gzip");
30 except ImportError:
31 '''return False;'''
32 try:
33 import bz2;
34 compression_list.append("bz2");
35 compression_list.append("bzip2");
36 except ImportError:
37 '''return False;'''
38 try:
39 import lz4;
40 compression_list.append("lz4");
41 except ImportError:
42 '''return False;'''
43 try:
44 import lzo;
45 compression_list.append("lzo");
46 compression_list.append("lzop");
47 except ImportError:
48 '''return False;'''
49 try:
50 import zstandard;
51 compression_list.append("zstd");
52 compression_list.append("zstandard");
53 except ImportError:
54 '''return False;'''
55 try:
56 import lzma;
57 compression_list.append("lzma");
58 compression_list.append("xz");
59 except ImportError:
60 '''return False;'''
61 return compression_list;
63 def CheckCompressionType(infile, closefp=True):
64 if(hasattr(infile, "read") or hasattr(infile, "write")):
65 ckcomfp = infile;
66 else:
67 ckcomfp = open(infile, "rb");
68 ckcomfp.seek(0, 0);
69 prefp = ckcomfp.read(2);
70 filetype = False;
71 if(prefp==binascii.unhexlify("1f8b")):
72 filetype = "gzip";
73 ckcomfp.seek(0, 0);
74 prefp = ckcomfp.read(3);
75 if(prefp==binascii.unhexlify("425a68")):
76 filetype = "bzip2";
77 ckcomfp.seek(0, 0);
78 prefp = ckcomfp.read(4);
79 if(prefp==binascii.unhexlify("28b52ffd")):
80 filetype = "zstd";
81 if(prefp==binascii.unhexlify("04224d18")):
82 filetype = "lz4";
83 ckcomfp.seek(0, 0);
84 prefp = ckcomfp.read(7);
85 if(prefp==binascii.unhexlify("fd377a585a0000")):
86 filetype = "lzma";
87 ckcomfp.seek(0, 0);
88 prefp = ckcomfp.read(9);
89 if(prefp==binascii.unhexlify("894c5a4f000d0a1a0a")):
90 filetype = "lzo";
91 ckcomfp.seek(0, 0);
92 if(closefp):
93 ckcomfp.close();
94 return filetype;
96 def gzip_file(infile, outfile, level=9, keepfile=True):
97 support_list = CompressionSupport();
98 if(not os.path.exists(infile) or not os.path.isfile(infile)):
99 return False;
100 if(os.path.exists(outfile)):
101 return False;
102 if("gzip" not in support_list):
103 return False;
104 import gzip;
105 ucfilefp = open(infile, "rb");
106 cfilefp = gzip.open(outfile, "wb", level);
107 shutil.copyfileobj(ucfilefp, cfilefp);
108 cfilefp.close();
109 ucfilefp.close();
110 if(CheckCompressionType(outfile)!="gzip"):
111 os.remove(outfile);
112 return False;
113 if(not keepfile):
114 os.remove(infile);
115 return True;
117 def gunzip_file(infile, outfile, keepfile=True):
118 support_list = CompressionSupport();
119 if(not os.path.exists(infile) or not os.path.isfile(infile)):
120 return False;
121 if(os.path.exists(outfile)):
122 return False;
123 if("gzip" not in support_list):
124 return False;
125 if(CheckCompressionType(infile)!="gzip"):
126 return False;
127 import gzip;
128 ucfilefp = open(outfile, "wb");
129 cfilefp = gzip.open(infile, "rb");
130 shutil.copyfileobj(cfilefp, ucfilefp);
131 cfilefp.close();
132 ucfilefp.close();
133 if(not keepfile):
134 os.remove(infile);
135 return True;
137 def bzip2_file(infile, outfile, level=9, keepfile=True):
138 support_list = CompressionSupport();
139 if(not os.path.exists(infile) or not os.path.isfile(infile)):
140 return False;
141 if(os.path.exists(outfile)):
142 return False;
143 if("bzip2" not in support_list):
144 return False;
145 import bz2;
146 ucfilefp = open(infile, "rb");
147 cfilefp = bz2.BZ2File(outfile, "wb", compresslevel=level);
148 shutil.copyfileobj(ucfilefp, cfilefp);
149 cfilefp.close();
150 ucfilefp.close();
151 if(CheckCompressionType(outfile)!="bzip2"):
152 os.remove(outfile);
153 return False;
154 if(not keepfile):
155 os.remove(infile);
156 return True;
158 def bunzip2_file(infile, outfile, keepfile=True):
159 support_list = CompressionSupport();
160 if(not os.path.exists(infile) or not os.path.isfile(infile)):
161 return False;
162 if(os.path.exists(outfile)):
163 return False;
164 if("bzip2" not in support_list):
165 return False;
166 if(CheckCompressionType(infile)!="bzip2"):
167 return False;
168 import bz2;
169 ucfilefp = open(outfile, "wb");
170 cfilefp = bz2.BZ2File(infile, "rb");
171 shutil.copyfileobj(cfilefp, ucfilefp);
172 cfilefp.close();
173 ucfilefp.close();
174 if(not keepfile):
175 os.remove(infile);
176 return True;
178 def zstd_file(infile, outfile, level=9, keepfile=True):
179 support_list = CompressionSupport();
180 if(not os.path.exists(infile) or not os.path.isfile(infile)):
181 return False;
182 if(os.path.exists(outfile)):
183 return False;
184 if("zstd" not in support_list):
185 return False;
186 import zstandard;
187 ucfilefp = open(infile, "rb");
188 cfilefp = zstandard.open(outfile, "wb", zstandard.ZstdCompressor(level=level));
189 shutil.copyfileobj(ucfilefp, cfilefp);
190 cfilefp.close();
191 ucfilefp.close();
192 if(CheckCompressionType(outfile)!="zstd"):
193 os.remove(outfile);
194 return False;
195 if(not keepfile):
196 os.remove(infile);
197 return True;
199 def unzstd_file(infile, outfile, keepfile=True):
200 support_list = CompressionSupport();
201 if(not os.path.exists(infile) or not os.path.isfile(infile)):
202 return False;
203 if(os.path.exists(outfile)):
204 return False;
205 if("zstd" not in support_list):
206 return False;
207 if(CheckCompressionType(infile)!="zstd"):
208 return False;
209 import zstandard;
210 ucfilefp = open(outfile, "wb");
211 cfilefp = zstandard.open(infile, "rb");
212 shutil.copyfileobj(cfilefp, ucfilefp);
213 cfilefp.close();
214 ucfilefp.close();
215 if(not keepfile):
216 os.remove(infile);
217 return True;
219 def lz4_file(infile, outfile, level=9, keepfile=True):
220 support_list = CompressionSupport();
221 if(not os.path.exists(infile) or not os.path.isfile(infile)):
222 return False;
223 if(os.path.exists(outfile)):
224 return False;
225 if("lz4" not in support_list):
226 return False;
227 import lz4;
228 ucfilefp = open(infile, "rb");
229 cfilefp = lz4.frame.open(outfile, "wb", compression_level=level);
230 shutil.copyfileobj(ucfilefp, cfilefp);
231 cfilefp.close();
232 ucfilefp.close();
233 if(CheckCompressionType(outfile)!="lz4"):
234 os.remove(outfile);
235 return False;
236 if(not keepfile):
237 os.remove(infile);
238 return True;
240 def unlz4_file(infile, outfile, keepfile=True):
241 support_list = CompressionSupport();
242 if(not os.path.exists(infile) or not os.path.isfile(infile)):
243 return False;
244 if(os.path.exists(outfile)):
245 return False;
246 if("lz4" not in support_list):
247 return False;
248 if(CheckCompressionType(infile)!="lz4"):
249 return False;
250 import lz4;
251 ucfilefp = open(outfile, "wb");
252 cfilefp = lz4.frame.open(infile, "rb");
253 shutil.copyfileobj(cfilefp, ucfilefp);
254 cfilefp.close();
255 ucfilefp.close();
256 if(not keepfile):
257 os.remove(infile);
258 return True;
260 def lzo_file(infile, outfile, level=9, keepfile=True):
261 support_list = CompressionSupport();
262 if(not os.path.exists(infile) or not os.path.isfile(infile)):
263 return False;
264 if(os.path.exists(outfile)):
265 return False;
266 if("lzo" not in support_list):
267 return False;
268 import lzo;
269 ucfilefp = open(infile, "rb");
270 cfilefp = open(outfile, "wb");
271 cfilefp.write(lzo.compress(ucfilefp.read(), level));
272 cfilefp.close();
273 ucfilefp.close();
274 if(CheckCompressionType(outfile)!="lzo"):
275 os.remove(outfile);
276 return False;
277 if(not keepfile):
278 os.remove(infile);
279 return True;
281 def unlzo_file(infile, outfile, keepfile=True):
282 support_list = CompressionSupport();
283 if(not os.path.exists(infile) or not os.path.isfile(infile)):
284 return False;
285 if(os.path.exists(outfile)):
286 return False;
287 if("lzo" not in support_list):
288 return False;
289 if(CheckCompressionType(infile)!="lzo"):
290 return False;
291 import lzo;
292 ucfilefp = open(outfile, "wb");
293 cfilefp = open(infile, "rb");
294 ucfilefp.write(lzo.decompress(cfilefp.read()));
295 cfilefp.close();
296 ucfilefp.close();
297 if(not keepfile):
298 os.remove(infile);
299 return True;
301 def lzma_file(infile, outfile, level=9, keepfile=True):
302 support_list = CompressionSupport();
303 if(not os.path.exists(infile) or not os.path.isfile(infile)):
304 return False;
305 if(os.path.exists(outfile)):
306 return False;
307 if("lzma" not in support_list):
308 return False;
309 import lzma;
310 ucfilefp = open(infile, "rb");
311 cfilefp = lzma.open(outfile, "wb", format=lzma.FORMAT_ALONE, preset=level);
312 shutil.copyfileobj(ucfilefp, cfilefp);
313 cfilefp.close();
314 ucfilefp.close();
315 if(CheckCompressionType(outfile)!="lzma"):
316 os.remove(outfile);
317 return False;
318 if(not keepfile):
319 os.remove(infile);
320 return True;
322 def unlzma_file(infile, outfile, keepfile=True):
323 support_list = CompressionSupport();
324 if(not os.path.exists(infile) or not os.path.isfile(infile)):
325 return False;
326 if(os.path.exists(outfile)):
327 return False;
328 if("lzma" not in support_list):
329 return False;
330 if(CheckCompressionType(infile)!="lzma"):
331 return False;
332 import lzma;
333 ucfilefp = open(outfile, "wb");
334 cfilefp = lzma.open(infile, "rb", format=lzma.FORMAT_ALONE);
335 shutil.copyfileobj(cfilefp, ucfilefp);
336 cfilefp.close();
337 ucfilefp.close();
338 if(not keepfile):
339 os.remove(infile);
340 return True;
342 def xz_file(infile, outfile, level=9, keepfile=True):
343 support_list = CompressionSupport();
344 if(not os.path.exists(infile) or not os.path.isfile(infile)):
345 return False;
346 if(os.path.exists(outfile)):
347 return False;
348 if("xz" not in support_list):
349 return False;
350 import lzma;
351 ucfilefp = open(infile, "rb");
352 cfilefp = lzma.open(outfile, "wb", format=lzma.FORMAT_XZ, preset=level);
353 shutil.copyfileobj(ucfilefp, cfilefp);
354 cfilefp.close();
355 ucfilefp.close();
356 if(CheckCompressionType(outfile)!="xz"):
357 os.remove(outfile);
358 return False;
359 if(not keepfile):
360 os.remove(infile);
361 return True;
363 def unxz_file(infile, outfile, keepfile=True):
364 support_list = CompressionSupport();
365 if(not os.path.exists(infile) or not os.path.isfile(infile)):
366 return False;
367 if(os.path.exists(outfile)):
368 return False;
369 if("xz" not in support_list):
370 return False;
371 if(CheckCompressionType(infile)!="xz"):
372 return False;
373 import lzma;
374 ucfilefp = open(outfile, "wb");
375 cfilefp = lzma.open(infile, "rb", format=lzma.FORMAT_XZ);
376 shutil.copyfileobj(cfilefp, ucfilefp);
377 cfilefp.close();
378 ucfilefp.close();
379 if(not keepfile):
380 os.remove(infile);
381 return True;
383 if __name__ == "__main__":
384 argparser = argparse.ArgumentParser(description="Compress Files", conflict_handler="resolve", add_help=True);
385 argparser.add_argument("-V", "--version", action="version", version="PyCompress 0.0.1");
386 argparser.add_argument("-c", "--compress", action="store_true", help="Compress file");
387 argparser.add_argument("-d", "--decompress", action="store_true", help="Decompress file");
388 argparser.add_argument("-i", "-f", "--input", help="Files to compress/decompress", required=True);
389 argparser.add_argument("-o", "--output", help="Output file after compress/decompress", required=True);
390 argparser.add_argument("-k", "--keep", action="store_false", help="Keep input file");
391 argparser.add_argument("-l", "--level", default="1", help="Compression level");
392 argparser.add_argument("-compression", "--compression", default="auto", help="File compression to use for compress/decompress");
393 getargs = argparser.parse_args();
394 chkcompression = CompressionSupport();
395 if(getargs.compression not in chkcompression):
396 exit();
397 if(not getargs.compress and not getargs.decompress):
398 exit();
399 if(getargs.compress and getargs.decompress):
400 exit();
401 if(getargs.compress and not getargs.decompress):
402 if(getargs.compression=="gzip" and "gzip" in chkcompression):
403 gzip_file(getargs.input, getargs.output, int(getargs.level), getargs.keep);
404 if(getargs.compression=="bzip2" and "bzip2" in chkcompression):
405 bzip2_file(getargs.input, getargs.output, int(getargs.level), getargs.keep);
406 if(getargs.compression=="zstd" and "zstd" in chkcompression):
407 zstd_file(getargs.input, getargs.output, int(getargs.level), getargs.keep);
408 if(getargs.compression=="lz4" and "lz4" in chkcompression):
409 lz4_file(getargs.input, getargs.output, int(getargs.level), getargs.keep);
410 if(getargs.compression=="lzo" and "lzo" in chkcompression):
411 lzo_file(getargs.input, getargs.output, int(getargs.level), getargs.keep);
412 if(getargs.compression=="lzma" and "lzma" in chkcompression):
413 lzma_file(getargs.input, getargs.output, int(getargs.level), getargs.keep);
414 if(getargs.compression=="xz" and "xz" in chkcompression):
415 xz_file(getargs.input, getargs.output, int(getargs.level), getargs.keep);
416 exit();
417 if(not getargs.compress and getargs.decompress):
418 if(getargs.compression=="gzip" and "gzip" in chkcompression):
419 gunzip_file(getargs.input, getargs.output, getargs.keep);
420 if(getargs.compression=="bzip2" and "bzip2" in chkcompression):
421 bunzip2_file(getargs.input, getargs.output, getargs.keep);
422 if(getargs.compression=="zstd" and "zstd" in chkcompression):
423 unzstd_file(getargs.input, getargs.output, getargs.keep);
424 if(getargs.compression=="lz4" and "lz4" in chkcompression):
425 unlz4_file(getargs.input, getargs.output, getargs.keep);
426 if(getargs.compression=="lzo" and "lzo" in chkcompression):
427 unlzo_file(getargs.input, getargs.output, getargs.keep);
428 if(getargs.compression=="lzma" and "lzma" in chkcompression):
429 unlzma_file(getargs.input, getargs.output, getargs.keep);
430 if(getargs.compression=="xz" and "xz" in chkcompression):
431 unxz_file(getargs.input, getargs.output, getargs.keep);
432 exit();