/Demo/zlib/minigzip.py

http://unladen-swallow.googlecode.com/ · Python · 133 lines · 102 code · 17 blank · 14 comment · 22 complexity · 4fd9d813d490c0e9e8b3cc7acb71da2c MD5 · raw file

  1. #!/usr/bin/env python
  2. # Demo program for zlib; it compresses or decompresses files, but *doesn't*
  3. # delete the original. This doesn't support all of gzip's options.
  4. #
  5. # The 'gzip' module in the standard library provides a more complete
  6. # implementation of gzip-format files.
  7. import zlib, sys, os
  8. FTEXT, FHCRC, FEXTRA, FNAME, FCOMMENT = 1, 2, 4, 8, 16
  9. def write32(output, value):
  10. output.write(chr(value & 255)) ; value=value // 256
  11. output.write(chr(value & 255)) ; value=value // 256
  12. output.write(chr(value & 255)) ; value=value // 256
  13. output.write(chr(value & 255))
  14. def read32(input):
  15. v = ord(input.read(1))
  16. v += (ord(input.read(1)) << 8 )
  17. v += (ord(input.read(1)) << 16)
  18. v += (ord(input.read(1)) << 24)
  19. return v
  20. def compress (filename, input, output):
  21. output.write('\037\213\010') # Write the header, ...
  22. output.write(chr(FNAME)) # ... flag byte ...
  23. statval = os.stat(filename) # ... modification time ...
  24. mtime = statval[8]
  25. write32(output, mtime)
  26. output.write('\002') # ... slowest compression alg. ...
  27. output.write('\377') # ... OS (=unknown) ...
  28. output.write(filename+'\000') # ... original filename ...
  29. crcval = zlib.crc32("")
  30. compobj = zlib.compressobj(9, zlib.DEFLATED, -zlib.MAX_WBITS,
  31. zlib.DEF_MEM_LEVEL, 0)
  32. while True:
  33. data = input.read(1024)
  34. if data == "":
  35. break
  36. crcval = zlib.crc32(data, crcval)
  37. output.write(compobj.compress(data))
  38. output.write(compobj.flush())
  39. write32(output, crcval) # ... the CRC ...
  40. write32(output, statval[6]) # and the file size.
  41. def decompress (input, output):
  42. magic = input.read(2)
  43. if magic != '\037\213':
  44. print 'Not a gzipped file'
  45. sys.exit(0)
  46. if ord(input.read(1)) != 8:
  47. print 'Unknown compression method'
  48. sys.exit(0)
  49. flag = ord(input.read(1))
  50. input.read(4+1+1) # Discard modification time,
  51. # extra flags, and OS byte.
  52. if flag & FEXTRA:
  53. # Read & discard the extra field, if present
  54. xlen = ord(input.read(1))
  55. xlen += 256*ord(input.read(1))
  56. input.read(xlen)
  57. if flag & FNAME:
  58. # Read and discard a null-terminated string containing the filename
  59. while True:
  60. s = input.read(1)
  61. if s == '\0': break
  62. if flag & FCOMMENT:
  63. # Read and discard a null-terminated string containing a comment
  64. while True:
  65. s=input.read(1)
  66. if s=='\0': break
  67. if flag & FHCRC:
  68. input.read(2) # Read & discard the 16-bit header CRC
  69. decompobj = zlib.decompressobj(-zlib.MAX_WBITS)
  70. crcval = zlib.crc32("")
  71. length = 0
  72. while True:
  73. data=input.read(1024)
  74. if data == "":
  75. break
  76. decompdata = decompobj.decompress(data)
  77. output.write(decompdata)
  78. length += len(decompdata)
  79. crcval = zlib.crc32(decompdata, crcval)
  80. decompdata = decompobj.flush()
  81. output.write(decompdata)
  82. length += len(decompdata)
  83. crcval = zlib.crc32(decompdata, crcval)
  84. # We've read to the end of the file, so we have to rewind in order
  85. # to reread the 8 bytes containing the CRC and the file size. The
  86. # decompressor is smart and knows when to stop, so feeding it
  87. # extra data is harmless.
  88. input.seek(-8, 2)
  89. crc32 = read32(input)
  90. isize = read32(input)
  91. if crc32 != crcval:
  92. print 'CRC check failed.'
  93. if isize != length:
  94. print 'Incorrect length of data produced'
  95. def main():
  96. if len(sys.argv)!=2:
  97. print 'Usage: minigzip.py <filename>'
  98. print ' The file will be compressed or decompressed.'
  99. sys.exit(0)
  100. filename = sys.argv[1]
  101. if filename.endswith('.gz'):
  102. compressing = False
  103. outputname = filename[:-3]
  104. else:
  105. compressing = True
  106. outputname = filename + '.gz'
  107. input = open(filename, 'rb')
  108. output = open(outputname, 'wb')
  109. if compressing:
  110. compress(filename, input, output)
  111. else:
  112. decompress(input, output)
  113. input.close()
  114. output.close()
  115. if __name__ == '__main__':
  116. main()