gzip
파일을 완전히 압축하지 않고도 파일의 압축 가능성을 추정하는 빠르고 더러운 방법이 있습니까 gzip
?
난 할 수 있어, 할 수 있어 bash
, 할 수 있어
bc <<<"scale=2;$(gzip -c file | wc -c)/$(wc -c <file)"
gz
이렇게 하면 파일을 디스크에 쓰지 않고도 압축 요소를 얻을 수 있습니다. 이렇게 하면 gz
디스크 공간 절약 효과가 번거로움을 정당화하기에 충분하지 않은 경우 디스크에 있는 파일을 해당 버전으로 바꾸는 것을 피할 수 있습니다. 그러나 이 접근 방식을 사용하면 파일이 완전히 전달됩니다 gzip
. 이는 출력이 디스크 wc
에 기록되는 것이 아니라 파이프로 전달된다는 것입니다.
gzip
파일의 전체 내용을 처리하지 않고 파일의 대략적인 압축 추정치를 얻을 수 있는 방법이 있습니까?
답변1
다음은 (아마도 동등한) Python 버전입니다.스티븐 차제라스 해결책
python -c "
import zlib
from itertools import islice
from functools import partial
import sys
with open(sys.argv[1], "rb") as f:
compressor = zlib.compressobj()
t, z = 0, 0.0
for chunk in islice(iter(partial(f.read, 4096), b''), 0, None, 10):
t += len(chunk)
z += len(compressor.compress(chunk))
z += len(compressor.flush())
print(z/t)
" file
답변2
예를 들어, 10개 블록마다 압축하여 아이디어를 얻을 수 있습니다.
perl -MIPC::Open2 -nE 'BEGIN{$/=\4096;open2(\*I,\*O,"gzip|wc -c")}
if ($. % 10 == 1) {print O $_; $l+=length}
END{close O; $c = <I>; say $c/$l}'
(여기서는 4K 블록).
답변3
여러 GB 크기의 파일이 있는데 압축되었는지 확실하지 않아서 처음 10M 바이트를 압축해 테스트했습니다.
head -c 10000000 large_file.bin | gzip | wc -c
완벽하지는 않지만 나에게는 잘 작동합니다.
답변4
이것은 iruvar 기반의 향상된 Python 버전입니다.훌륭한 솔루션. 주요 개선 사항은 스크립트가 실제로 압축한 디스크의 데이터 블록만 읽는다는 것입니다.
import zlib
def Predict_file_compression_ratio(MyFilePath):
blocksize = (4096 * 1) # Increase if you want to read more bytes per block at once.
blocksize_seek = 0
# r = read, b = binary
with open(MyFilePath, "rb") as f:
# Make a zlib compressor object, and set compression level.
# 1 is fastest, 9 is slowest
compressor = zlib.compressobj(1)
t, z, counter = 0, 0, 0
while True:
# Use this modulo calculation to check every "number" of blocks.
if counter % 10 == 0:
# Seek to the correct byte position of the file.
f.seek(blocksize_seek)
# The block above will be read, increase the seek distance by one block for the next iteration.
blocksize_seek += blocksize
# Read data chunk of file into this variable.
data = f.read(blocksize)
# Stop if there are no more data.
if not data:
# For zlib: Flush any remaining compressed data. Not doing this can lead to a tiny inaccuracy.
z += len(compressor.flush())
break
# Uncompressed data size, add size to variable to get a total value.
t += len(data)
# Compressed data size
z += len(compressor.compress(data))
# When we skip, we want to increase the seek distance. This is vital for correct skipping.
else:
blocksize_seek += blocksize
# Increase the block / iteration counter.
counter += 1
# Print the results. But avoid division by 0 >_>
if not t == 0:
print('Compression ratio: ' + str(z/t))
else:
print('Compression ratio: none, file has no content.')
print('Compressed: ' + str(z))
print('Uncompressed: ' + str(t))
높은 데이터 속도가 중요하고 정확한 압축 비율이 그다지 중요하지 않은 경우 lz4를 사용할 수 있습니다. 이는 낮은 CPU 사용량으로 가장 많이 압축할 수 있는 파일을 찾으려는 경우에 유용합니다. 이 모듈은 pip를 사용하여 설치해야 합니다.여기에서. Python 코드 자체에서는 이것이 필요한 전부입니다.
import lz4.block
z += len(lz4.block.compress(data))
이 스크립트를 사용하면 여분의 메모리가 파괴되어(확실히 Windows에서) 파일 성능이 저하될 수 있다는 점을 관찰했습니다. 특히 기존 하드 드라이브가 있는 시스템에서 그리고 한 번에 많은 수의 파일에 이 기능을 사용하는 경우 더욱 그렇습니다. 스크립트의 Python 프로세스에서 낮은 메모리 페이지 우선순위를 설정하면 이러한 메모리 낭비를 피할 수 있습니다. 저는 이 작업을 위해 Windows에서 AutoHotkey를 사용하기로 결정했습니다. 유용한 소스여기.