sábado, 25 de enero de 2014

extract-txt-bin-portions.pl: programa el Perl para encontrar cadenas UTF-8 en archivos binarios sin formato

# Lee un archivo mixto UTF-8 - no UTF-8
# output:
# Repeticiones de las líneas de texto:
# "bin: " byte-inicial-secuencia-no-UTF-8 byte-final-secuencia-no-UTF-8
# "txt: " byte-inicial-secuencia-UTF-8 byte-final-secuencia-UTF-8
# por orden de aparición de las secuencias (orden normal de los bytes dentro del archivo)

open my $fh, "<:raw", @ARGV[0] or die "cannot open < @ARGV[0]: $!";
my $i = 0;
my $ini_ciclo_bin = 1;

my $length = read $fh, my $byte, 1;
$i += $length;
# print "a ".unpack("B*", $byte) . "\n";

my $ini_bin;
my $fin_bin;
my $ini_txt;
my $fin_txt;


while($length) {
# ciclo bin
while($length and not unpack("B*", $byte) =~ /^(0|110|1110|11110|111110|1111110).*/) {
$length = read $fh, $byte, 1;
$i += $length;
# print "b ".unpack("B*", $byte) . "\n";
}

# ciclo txt
# inicialización secuencia txt
$ini_txt = $i;
$fin_txt = 0; # no def
my $s_val = 1;   # boolean TRUE, secuencia txt válida (secuencia de caracteres)
while($length and unpack("B*", $byte) =~ /^(0|110|1110|11110|111110|1111110).*/ and $s_val) {
# inicialización 1 caracter
my $l = index(unpack("B*", $byte),'0');
if($l eq 0) {
$l = 1;
}
my $ini_sec_bytes = $i;

# lectura 1 caracter
while($length and $i-$ini_sec_bytes+1 lt $l and $s_val) {
$length = read $fh, $byte, 1;
$i += $length;
# print "c ".unpack("B*", $byte) . "\n";
if(not unpack("B*", $byte) =~ /^10.*/) {
$s_val = 0;   # boolean FALSE
}
}

if($s_val and $i-$ini_sec_bytes+1 eq $l) {
$fin_txt = $i;   # def
$length = read $fh, $byte, 1;
$i += $length;
# print "d ".unpack("B*", $byte) . "\n";
}
}

# delimitar secuencias
if($fin_txt) {   # secuencia txt no vacía
if($ini_txt ne $ini_ciclo_bin) {   # secuencia binaria no vacía
$ini_bin = $ini_ciclo_bin;
$fin_bin = $ini_txt - 1;
print "bin: $ini_bin $fin_bin\n";
}
print "txt: $ini_txt $fin_txt\n";
$ini_ciclo_bin = $fin_txt + 1;   # para la vuelta entrante
}   # si no las condiciones continúan igual para reentrar el ciclo-bin
}
# delimitación final
if($i) {   # archivo no vacío
if($fin_txt and $fin_txt ne $i) {   # secuencia txt no vacía ($fin_txt) and quedaron ($i-$fin_txt) bytes bin al final del archivo
$ini_bin = $fin_txt + 1;
$fin_bin = $i;
print "bin: $ini_bin $fin_bin\n";
}
elsif($fin_txt eq 0) {   # último ciclo txt vacío ==> todo el ciclo corresponde a datos bin
$ini_bin = $ini_ciclo_bin;
$fin_bin = $i;
print "bin: $ini_bin $fin_bin\n";
}
# si no si ($fin_txt eq $i) el archivo termina justo en una secuencia txt, último OUTPUT emitido en ciclo txt
}

close $fh;

No hay comentarios: