1 byte: 0..127 2 bytes: 128..etc 3 bytes: 16_384 4 bytes: 2_097_152 5 bytes: 268_435_456 6 bytes: 34_359_738_368 7 bytes: 4_398_046_511_104 8 bytes: 562_949_953_421_312 9 bytes: 72_057_594_037_927_936 #### sub compress_uint { my ($uint) = @_; my $compressed = ''; while ($uint >= 128) { $compressed .= chr(($uint & 127) | 128); $uint >>= 7; } $compressed .= chr($uint); } for (100, 1000, 100000) { print $fh compress_uint($_); } #### sub decompress_uint { our $compressed; local *compressed = \($_[0]); my $bytes_read = 0; my $uint = 0; for (;;) { die if length($compressed) == $bytes_read; my $byte = ord(substr($compressed, $bytes_read++, 1)); $uint = ($uint << 7) | ($byte & 127); last if $byte & 128; } $compressed = substr($compressed, $bytes_read); } my $raw = do { local $/; <$fh> }; my @nums; while (length($raw)) { push @nums, decompress_uint($raw); }