2014-10-30 3 views
0

мой скрипт генерирует очень очень большие файлы, и я пытаюсь распечатать/сохранить вывод в двоичном формате, чтобы максимально уменьшить размер файла!печать и сохранение данных в двоичном формате в perl

каждый раз, когда скрипт генерирует 5 значений, например:

$a1 = 1.64729 
$a2 = 4.33329 
$a3 = 3.55724 
$a4 = 1.45759 
$a5 = 7.474700 

Он печатает на выходе, как:

A:1.64729,4.33329,3.55724,1.45759,7.474700 

Я не уверен, является ли это лучший способ, но я думал, чтобы упаковать каждая строка при печати на выходе! Я использовал встроенную функцию pack/unpack в perl!

Я взглянул на perldoc, но не понял, какие форматированные спецификации являются правильными (???)!

#!/usr/bin/perl 

... 

@A = ($a1,$a2,$a3,$a4,$a5); 

print pack ("???", ("A:",join(",", map { sprintf "%.1f", $_ } @A)),"\n"; 
+0

Вы, вероятно, лучше всего используете сжатие всего файла. вы можете сжать его, пока вы его пишете, и расстегните его, когда вы его прочитаете, если это необходимо. насколько велика «очень огромная»? – ysth

+0

1000 файлов, каждый сжатый файл 1.7 G – EpiMan

ответ

1

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

Вы можете сжать файл по мере его записи через IO::Zlib. Это будет использовать либо библиотеку Zlib, либо команду gzip.

Однако, если вы хотите использовать pack, то вперед. Получите Camel Book, который дает гораздо более четкую документацию, чем стандартный Perldoc.

Это не так уж и сложно:

my $output = "A:1.64729,4.33329,3.55724,1.45759,7.474700"; 
$output =~ s/^A://;     #Remove the 'A:' 
my @numbers = split /,/, $output  # Make into an array 
my $packed = pack "d5", @numbers; # Pack five inputs as floating point numbers 
say join ",", "d5", $packed;   # Unpacks those five decimal encoded numbers 

Вы, вероятно, придется использовать syswrite и sysread, поскольку не читать и писать строки. Это небуферизованное чтение и запись, и вы должны указать количество байтов, которые вы читаете или записываете.

Еще одна вещь: если вы знаете, где находится десятичная точка в количестве (то есть, это всегда число от 1 до 10), вы можете преобразовать число в целое число, которое позволит вам pack число в еще меньшее количество байтов:

my $output = "A:1.64729,4.33329,3.55724,1.45759,7.474700"; 
$output =~ s/^A://;     #Remove the 'A:' 
$output =~ s/,//g;     #Remove all the decimal points 
my @numbers = split /,/, $output  # Make into an array 
my $packed = pack "L5", @numbers; # Pack five inputs as unsigned long numbers 
+0

спасибо, очень полезно! :) – EpiMan

Смежные вопросы