Я использую Perl (5.8.8, не спрашивайте) и просматриваю сериализованный двоичный файл, из которого хочу проанализировать и извлечь информацию.
Формат следующий:
- 7 байт, значение которых мне неизвестно (DB DB 00 00 7A 03 00)
- ноль (0x00)
- 7-байтовая строка с идентификатором пользователя
- ноль (0x00)
- 12-байтовая строка, которую нужно отбросить
- ноль (0x00)
- 3-байтовое число, указывающее количество элементов, за которыми следует
- ноль (0x00)
- строка переменной длины для первого элемента
- новая строка (0x0a)
- строка переменной длины для второго элемента
- новая строка (0x0a)
- и т.д ...
- ноль (0x00)
- 7-байтовая строка с идентификатором пользователя
- и т.д ...
Мой текущий код несколько наивно пропускает первые 8 байтов, затем считывает байт за байтом, пока не достигнет нуля, а затем выполняет очень специфический синтаксический анализ.
sub readGroupsFile {
my %index;
open (my $fh, "<:raw", "groupsfile");
seek($fh, 8, 0);
while (read($fh, my $userID, 7)) {
$index{$userID} = ();
seek($fh, 18, 1);
my $groups = "";
while (read($fh, my $byte, 1)) {
last if (ord($byte) == 0);
$groups .= $byte;
}
my @grouplist = split("\n", $groups);
$index{$userID} = \@grouplist;
}
close($fh);
return \%index;
}
Хорошие новости? Оно работает.
Тем не менее, я думаю, что это не очень элегантно, и мне интересно, могу ли я использовать 2-байтовое число, указывающее количество элементов, которым нужно следовать, в моих интересах, чтобы ускорить синтаксический анализ. Я понятия не имею, почему еще это было бы там.
Я думаю, что unpack()
и его шаблоны могут дать ответ, но я не могу понять, как он может работать с массивами строк переменной длины с их собственной переменной длиной.
unpack
нужна строка для распаковки, она не может читать напрямую из файла. Итак, вам нужно сначала прочитать файл в строку, но это может быть не очень эффективно по сравнению с тем, что у вас есть. - person Håkon Hægland   schedule 02.08.2019readline
(он же<>
), так как все они заканчиваются символом новой строки. Я думаю, нет причин не смешиватьread
и<>
(только неsysread
, который не буферизован). - person zdim   schedule 02.08.2019readline
, вы сможете проверить каждую прочитанную строку на наличие 7-байтовой строки, заканчивающейся нулем; по описанию кажется, что ни один предмет не может быть таким. - person zdim   schedule 02.08.2019local $/
в nul, затем прочитайте четыре таких строки (отбросить -- идентификатор пользователя -- отбросить -- количество элементов, которые нужно следовать); Затем измените$/
обратно на новую строку и, используя последнюю только что прочитанную (количество элементов), прочитайте столько строк (элементов). Повторить? - person zdim   schedule 02.08.2019