Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Perl: Системное программирование > работа с двоичными последовательностями


Автор: Aleksandor 8.12.2005, 12:46
Уважаемые знатоки! У меня такие вопросы
1. что означает такая конструкция в переводе на русский-
my (@buf, $buff)
(это не по теме, просто интересно)

Дальше собственно сабж...
2. как выделить первые 4 байта в виде отдельной переменной из последовательности
длиной 36 байт?
и
3. - вопрос в коде (как заменить первые 4 байта в переменной $buff длиной 36 байт)
Код

my $datalengh=36;  
my (@buf, $buff);
my $value;

my $bin_a=pack("H8",$params[1]);
my $zero=pack("H8","00000000");

while (read(FH,$buff,$datalengh)) {  # читаем по 36 байт из двоичного файла
        # как выделить первые 4 байта в виде переменной $value ???
if ($value == $zero) $value=$bin_b;   #  меняем значение
        # как первые 4 байта в $buff поменять на значение $value ??? 
push (@buf,$buff);
} 


Вопрос 4 - имеются 9 двоичных переменных, каждая длиной 4 байта.
как их упаковать для записи в массив в виде непрерывной последовательности из 36 байт?

my $bin_a=pack("H8",$params[0]);
my $bin_m1=pack("H8",$params[2]);
my $bin_m2=pack("H8",$params[3]);
my $bin_m3=pack("H8",$params[4]);
my $bin_m4=pack("H8",$params[5]);
my $bin_m5=pack("H8",$params[6]);
my $bin_m6=pack("H8",$params[7]);
my $bin_m7=pack("H8",$params[8]);
my $bin_m8=pack("H8",$params[9]);

# как все эти переменные упаковать в $buff ???
push(@buf, $buff); # записываем в массив smile

Автор: Aleksandor 8.12.2005, 20:47
Кажется немного разобрался сам smile
для упаковки строковых переменных такая конструкция-
Код

my @longwords;    # массив бинарных переменных
my $step=0;

for ($step=0; $step<9; $step++) {   
    push(@longwords,pack("H8",$params[$step]);  # строковые в params
}


Для распаковки двоичной последовательности
Код

my $datalengh=36;
my @buf;
my $buff;
my @filelongwords;

while (read(FH,$buff,$datalengh)) {
 
    @filelongwords = unpack("L*", $buff);     # распаковка
     for ($step=0; $step<9; $step++) {         # обратно в двоичное представление
    $filelongwords[$step]=pack("L*",$filelongwords[$step]);
   }  

 # замена значения первой переменной
 if ($bin_c eq $bin_a)   { $filelongwords[0]=$bin_b; } 

 # запись обратно в массив
 push (@buf,@filelongwords);



Добавление нового значения в конец массива
push(@buf, @longwords);

Сохранение в файле
print FH for @buf;

Прошу прояснить если в чем не прав и что здесь можно оптимизировать для повышения быстродействия. smile

Автор: sharq 9.12.2005, 17:19
Aleksandor например, использовать не массив, а ссылку на массив.

Автор: Aleksandor 9.12.2005, 17:30
Цитата
...использовать не массив, а ссылку на массив


Sharq, а где конкретно? И что это дает?
А в остальном (push (@buf,@filelongwords);=- массив в массив smile ) это нормально?

Хочется чтоб было красиво, но Perl толком не знаю smile


А как понять еще вот такое выражение my (@buf, $buff) ???



Автор: korob2001 9.12.2005, 20:50
Посмотри эту тему, там несколько рабочих примеров работы с бинарными файлами. Так же есть коментарии.
http://forum.vingrad.ru/index.php?showtopic=71224

Автор: Aleksandor 9.12.2005, 21:45
А так это я и был smile Только не зарегившись по первости...

Сейчас решил к единственной переменной длиной 4 байт добавить еще ключ длиной 32 байта.
Таким образом эти 36 байт составляют одну "запись" или "строку" в файле.

Не уверен что можно иметь массив с переменными разной размерности, поэтому разбиваю эти 36 байт на 9 переменных одинакового типа.
Первая переменная используется для сравнения (поиска) в массиве и иногда для подстановки.

К сожалению не нашел способа выделить двоичные данные не преобразуя их в строковые значения smile Приходится распаковывать и снова упаковывать!





Автор: korob2001 10.12.2005, 12:18
Код

my (@buf, $buff)

Это равносильно следующему.
Код

my @buf;
my $buff;

В обоих случаях объявляются массив @buf и скаляр $buff. Ну вот собственно и всё.

Автор: sharq 10.12.2005, 12:43
Продолжаю эквивалентность
Код

my @buf = (); # объявляется пустой список


Код

my $buff = ''; 
#или 
my $buff = 0; 
#или 
my $buff = undef; 


Aleksandor

1.
Если весь массив @params, то
Код

my $longwords;    # ссылка на массив бинарных переменных
push @$lonwords, pack('H8', $_) foreach @params;


Если, только 9 первых элементов, то
Код

my $longwords;    # ссылка на массив бинарных переменных
push @$lonwords, pack('H8', $_) foreach (@params[0..8]); # здесь используется срез массива
# или
push @$lonwords, pack('H8', $_) foreach map {$params[$_]} (0..8);
# или 
my $step;
while ($step<9) {
 push @$lonwords, pack('H8', $params[$step]);
 $step++;
}
# или 
for (my $step=0; $step<9; $step++) {
 push @$lonwords, pack('H8', $params[$step]);
}


2.

Код

my $datalengh=36;
my @buf;
while (read(FH,my $buff,$datalengh)) {
     my @filelongwords = unpack("L*", $buff);     # распаковка
     for (my $step=0; $step<9; $step++) {         # обратно в двоичное представление
        $filelongwords[$step]=pack("L*",$filelongwords[$step]);
     }  
     # замена значения первой переменной
     $filelongwords[0]=$bin_b if $bin_c eq $bin_a; 
     # запись обратно в массив
     push @buf, @filelongwords;
}


ВОт посмотри, потестируй, поэкспериментируй.

Только не забывай про
Код

use strict;
use warnings;

Они научат тебя писать скрипты на perl правильно. smile

Почитай книги по perl, здесь уже ни раз обсуждалось какие и где взять.

smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)