Как я могу писать сжатые файлы на лету, используя Perl? - PullRequest
1 голос
/ 28 сентября 2010

Я генерирую относительно большие файлы, используя Perl. Файлы, которые я генерирую, бывают двух видов:

  1. Табличные файлы, то есть текстовые файлы, которые я печатаю построчно (строка за строкой), которые содержат в основном числа. Типичная линия выглядит так:

    126891 126991 14545 12

  2. Сериализованные объекты, которые я создаю и сохраняю в файл, используя Storable::nstore Эти объекты обычно содержат большой хеш с числовыми значениями. Значения в объекте могли быть pack отредактированы для экономии места (и объект unpack s каждое значение перед его использованием).

В настоящее время я обычно делаю следующее:

use IO::Compress::Gzip qw(gzip $GzipError);

# create normal, uncompressed file ($out_file)
# ...

# compress file using gzip
my $gz_out_file = "$out_file.gz";
gzip $out_file => $gz_out_file or die "gzip failed: $GzipError";

# delete uncompressed file
unlink($out_file) or die "can't unlink file $out_file: $!";

Это довольно неэффективно, так как я сначала записываю большой файл на диск, затем gzip снова читаю его и сжимаю. Поэтому мои вопросы следующие:

  1. Могу ли я создать сжатый файл без предварительной записи файла на диск? Можно ли создать сжатый файл последовательно, то есть печатать построчно, как в сценарии (1), описанном ранее?

  2. Звучит ли Gzip как подходящий выбор? Есть ли другие рекомендованные компрессоры для данных, которые я описал?

  3. Имеет ли смысл pack значений в объекте, которые впоследствии все равно будут сохранены и сжаты?

Мои соображения сводятся в основном к экономии дискового пространства и последующей быстрой декомпрессии.

Ответы [ 3 ]

8 голосов
/ 28 сентября 2010
  1. Вы можете использовать IO::Zlib или PerlIO::gzip, чтобы связать дескриптор файла для сжатия на лету.

  2. Что касается того, какие компрессоры подходят, просто попробуйте несколько и посмотрите, как они работают с вашими данными. Также следите за тем, сколько процессоров / памяти они используют для сжатия и распаковки.

  3. Опять же, проверьте, насколько pack помогает с вашими данными и насколько это влияет на вашу производительность. В некоторых случаях это может быть полезно. В других это не может. Это действительно зависит от ваших данных.

2 голосов
/ 28 сентября 2010

Вы также можете открыть () файловый дескриптор в скаляре вместо реального файла и использовать этот файловый дескриптор с IO :: Compress :: Gzip. На самом деле не пробовал, но это должно сработать. Я использую нечто подобное с Net :: FTP, чтобы избежать создания файлов на диске.

Начиная с версии 5.0.0, Perl создавался с использованием PerlIO по умолчанию. Если вы не изменили это (т.е. сконфигурировали -Uuseperlio), вы можете открывать файловые дескрипторы непосредственно в скалярах Perl с помощью:

open($fh, '>', \$variable) || ..

из открыто ()

0 голосов
/ 07 марта 2013

IO :: Compress :: Zlib имеет интерфейс OO, который можно использовать для этого.

use strict;  
use warnings;
use IO::Compress::Gzip;

my $z = IO::Compress::Gzip->new('out.gz');
$z->print($_, "\n") for 0 .. 10;
...