Comment lire un fichier binaire en Perl
Je vais avoir un problème avec l'écriture d'un script Perl pour lire un fichier binaire.
Mon code est le suivant laquelle le $file
sont des fichiers au format binaire. J'ai essayé de chercher dans le web et de les appliquer dans mon code, essayé de l'imprimer, mais il semble que cela ne fonctionne pas bien.
Actuellement, il n'imprime que le '&&&&&&&&&&&" et ""ppppppppppp", mais ce que je veux vraiment c'est qu'elle peut imprimer chacune des $line
, afin que je puisse faire quelque chose d'autre que le post-traitement plus tard. Aussi, je ne suis pas tout à fait sûr de ce que l' $data
est que je vois c'est la partie du code à partir de l'exemple dans l'article, en indiquant suppose être un scalaire. J'ai besoin de quelqu'un qui peut cerner le point de m'où l'erreur ne va pas dans mon code. Ci-dessous est ce que j'ai fait.
my $tmp = "$basedir/$key";
opendir (TEMP1, "$tmp");
my @dirs = readdir(TEMP1);
closedir(TEMP1);
foreach my $dirs (@dirs) {
next if ($dirs eq "." || $dirs eq "..");
print "---->$dirs\n";
my $d = "$basedir/$key/$dirs";
if (-d "$d") {
opendir (TEMP2, $d) || die $!;
my @files = readdir (TEMP2); # This should read binary files
closedir (TEMP2);
#my $buffer = "";
#opendir (FILE, $d) || die $!;
#binmode (FILE);
#my @files = readdir (FILE, $buffer, 169108570);
#closedir (FILE);
foreach my $file (@files) {
next if ($file eq "." || $file eq "..");
my $f = "$d/$file";
print "==>$file\n";
open FILE, $file || die $!;
binmode FILE;
foreach ($line = read (FILE, $data, 169108570)) {
print "&&&&&&&&&&&$line\n";
print "ppppppppppp$data\n";
}
close FILE;
}
}
}
J'ai modifié mon code pour que cela se passe comme ci-dessous. Maintenant, je peux lire les $données. Merci J-16 SDiZ pour préciser que. Je suis en train de pousser les infos que j'ai obtenu à partir du fichier binaire dans un tableau appelé "tableau", thinkking de filtrer les données à partir du tableau de chaîne de caractères selon le match "p04" mais échouent. Quelqu'un peut-il point où est l'erreur?
my $tmp = "$basedir/$key";
opendir (TEMP1, "$tmp");
my @dirs = readdir (TEMP1);
closedir (TEMP1);
foreach my $dirs (@dirs) {
next if ($dirs eq "." || $dirs eq "..");
print "---->$dirs\n";
my $d = "$basedir/$key/$dirs";
if (-d "$d") {
opendir (TEMP2, $d) || die $!;
my @files = readdir (TEMP2); #This should read binary files
closedir (TEMP2);
foreach my $file (@files) {
next if ($file eq "." || $file eq "..");
my $f = "$d/$file";
print "==>$file\n";
open FILE, $file || die $!;
binmode FILE;
foreach ($line = read (FILE, $data, 169108570)) {
print "&&&&&&&&&&&$line\n";
print "ppppppppppp$data\n";
push @array, $data;
}
close FILE;
}
}
}
foreach $item (@array) {
#print "==>$item<==\n"; # It prints out content of binary file without the ==> and <== if I uncomment this.. weird!
if ($item =~ /p04(.*)/) {
print "=>$item<===============\n"; # It prints "=><===============" according to the number of binary file I have. This is wrong that I aspect it to print the content of each binary file instead :(
next if ($item !~ /^w+/);
open (LOG, ">log") or die $!;
#print LOG $item;
close LOG;
}
}
Encore une fois, j'ai modifié mon code comme le suivant, mais ça ne fonctionne toujours pas car il ne sont pas en mesure de filtrer les "p04" correctement en vérifiant sur le fichier "log". Il n'grep l'ensemble du dossier, y compris les binaires du genre "@^@^@^@^G^D^@^@^@^^@p04bbhi06^@^^@^@^@^@^@^@^@^@hh^R^@^@^@^^@^@^@p04lohhj09^@^@^@^^@@" . Ce que je suis aspecting est qu'il ne grep quoi que ce soit avec p04 seulement comme grepping p04bbhi06 et p04lohhj09. Voici comment mon code va:-
foreach my $file (@files) {
next if ($file eq "." || $file eq "..");
my $f = "$d/$file";
print "==>$file\n";
open FILE, $f || die $!;
binmode FILE;
my @lines = <FILE>;
close FILE;
foreach $cell (@lines) {
if ($cell =~ /b12/) {
push @array, $cell;
}
}
}
#my @matches = grep /p04/, @lines;
#foreach $item (@matches) {
foreach $item (@array) {
#print "-->$item<--";
open (LOG, ">log") or die $!;
print LOG $item;
close LOG;
}
use autodie
- Il n'y a pas une telle chose comme "format binaire'. Veuillez être plus précis. Quel est le format des fichiers dans? Quelles sont les caractéristiques qu'ils ont que vous appelez "en format binaire'?
- Il est en cours .gds format. Ce fichier est capable de lire dans Unix avec des chaînes de commandement. Il a été reaable dans mon script Perl mais je ne suis pas en mesure de filtrer les données que je voulais (p04* ici, dans mon code) .
- Comme l'a déjà suggéré, utilisez File::Find ou quelque chose pour obtenir votre liste de fichiers. Pour le reste, que voulez-vous vraiment? Sortie de l'ensemble du contenu du fichier si vous avez trouvé un match? Ou juste les parties de ce match? Et que voulez-vous correspondre?
p04(.*)
correspond à quelque chose de "p04" jusqu'à la prochaine ligne. Vous avez, ensuite, que "quelque chose" dans$1
. Laisser tous les maladroits répertoire de trucs et de se concentrer d'abord sur ce que vous voulez à partir d'un seul fichier. Quelle est la taille des fichiers? Vous êtes seulement à la lecture de la première 170MB. Et vous continuez à vous d'écraser le fichier "log", de sorte qu'il ne contient que le dernier point du dernier fichier. - les OP dans le cadre du "fichier binaire" signifie probablement à l'opposé des fichiers de texte - par exemple, même chose que dans le perldoc s -X de la documentation voir le
-B
explication. (citer:-B
est un Fichier "binaire" fichier (en face de l'-T).)
Vous devez vous connecter pour publier un commentaire.
Utilisation:
Les données sont dans
$data
; et$line
est le nombre d'octets lus.Je suppose que le chemin d'accès complet est en
$f
, mais vous êtes ouverture$file
. (Dans mes tests, même$f
n'est pas le chemin d'accès complet, mais je suppose que vous avez peut-être une autre colle le code...)Si vous voulez juste pour marcher tous les fichiers dans un répertoire, essayez
File::DirWalk
ouFile::Find
.Je ne suis pas sûr si j'ai bien compris vous avez droit.
Si vous avez besoin pour lire un fichier binaire, vous pouvez faire la même chose que pour un fichier texte:
Sous Windows, vous devrez peut-être ajouter
binmode F;
sous *nix, il fonctionne sans elle.Si vous avez besoin de trouver les lignes dans un tableau contient un mot, vous pouvez utiliser
grep
fonction:Vous obtiendrez tous appariés lignes dans le nouveau tableau
@matches
.BTW: je ne pense pas que c'est une bonne idée de lire des tonnes de fichiers binaires en mémoire à la fois. Vous pouvez effectuer une recherche 1 par 1...
Si vous avez besoin de trouver où le match se produit, vous pouvez utiliser une autre fonction de base,
index
:Je ne suis pas sûr que je vais être en mesure de répondre à l'OP question exactement, mais voici quelques remarques qui peuvent être liés. (edit: c'est la même approche que la réponse par @Dimanoid, mais avec plus de détails)
Dire que vous avez un fichier, qui est un mélange de données ASCII et binaires. Voici un exemple dans un
bash
terminal:Noter que les octets
00
(spécifié comme\x00
) est un caractère non imprimable, (et dansC
, il signifie aussi "fin de chaîne") - ainsi, sa présence rendtester.txt
un fichier binaire. Le fichier a une taille de 13 octets comme on le voit pardu
, en raison de la fuite\n
ajouté par leecho
(comme il peut être vu à partir dehexdump
).Maintenant, nous allons voir ce qui se passe quand on essaie de le lire avec
perl
's<>
diamant de l'opérateur (voir aussi Quelle est l'utilisation de <> en perl?):Clairement, le fichier n'a pas l'obtenir slurped - il s'est cassé à l'extrémité de la ligne de
\n
(et pas le binaire\x00
). C'est parce que le diamant descripteur de fichier<FH>
opérateur est en fait le raccourci pourreadline
(voir Perl livre de recettes: Chapitre 8, le Contenu du Fichier)Le même lien indique que l'on doit le fnud l'enregistrement de l'entrée du séparateur,
\$
(qui par défaut est réglé sur\n
), afin de siphonner la totalité du fichier. Vous voudrez peut-être avoir ce changement soit seulement local, qui est pourquoi les accolades etlocal
sont utilisés à la place deundef
(voir Perl Idiomes, Explique - my $chaine = do { local $/; };); nous avons donc:... et maintenant nous pouvons voir le fichier est slurped dans son intégralité.
Depuis de données binaires implique des caractères non imprimables, vous pouvez inspecter le contenu réel de
$data
par l'impression viasprintf
oupack
/unpack
à la place.Espère que cela aide quelqu'un,
Cheers!