Re: Binary conditionals
by moritz (Cardinal) on Sep 30, 2008 at 14:22 UTC
|
So you want to substitute all zero bytes with 0x17?
open my $in, '<:raw', 'infile.dat' or die $!;
open my $out, '>:raw', 'outfile.dat' or die $!;
# reading with a bigger block size is much more efficient
# than byte by byte reading
local $/ = \1024;
while (<$in>) {
my $copy = $in;
$copy =~ s/\x00/\x17/g;
print $out $copy;
}
close $in or die $!;
close $out or die $!;
Your code fails because it writes the number 23 (0x17), not the character 23. You can fix that with the chr function. | [reply] [d/l] [select] |
|
|
| [reply] [d/l] |
|
|
Just as an aside, you should also open the file in binmode. Generally only important on Windows, it is just good practice to specify it.
| [reply] |
|
|
| [reply] [d/l] [select] |
|
|
|
|
Ok, I can't do a simple s/// because I actually have to rotate them. It's something with the conditional or the assignment. I tried updating the code in this manner
#!/usr/bin/perl
open my $in, '<:raw', 'out.dat' or die $!;
open my $out, '>:raw', 'outfile.jpg' or die $!;
local $/ = \1024;
my $byte;
while (read($in, $byte, 1)) {
if($byte == x00){
$byte = chr(x17);}
elsif($byte == x17){
$byte = chr(x00);}
elsif($byte == x4E){
$byte = chr(x42);}
elsif($byte == x42){
$byte = chr(x4E);}
elsif($byte == x24){
$byte = chr(x90);}
elsif($byte == x90){
$byte = chr(x24);}
print $out $byte;
}
close $in or die $!;
close $out or die $!;
all it prints is many nulls and sporadic digits 1..9. I've even tried this with an if($byte eq chr(x00)) but it doesn't work eighther. | [reply] |
|
|
Always start your scripts with
use strict;
use warnings;
It catches many of your errors. The correct comparison is either $byte eq "\x00" or $byte eq chr(0x00).
You can still use a substitution if your mapping is constant:
my %table = (
"\x00" => "\x17",
"\x17" => "\x00",
...
);
my $re = join '|', map quotemeta, keys %table;
# open in and out files...
# and then substitute:
$str =~ s/($re)/$table{$1}/g
| [reply] [d/l] [select] |
|
|
|
|
while (<$in>) {
tr/\x00\x17\x4E\x42\x24\x90/\x17\x00\x42\x4E\x90\x24/;
print $out $_;
}
| [reply] [d/l] [select] |
Re: Binary conditionals
by Narveson (Chaplain) on Sep 30, 2008 at 14:45 UTC
|
Now that moritz has answered your question, I have a question of my own.
I can't compile
my IN, "<infile.dat";
my OUT, ">outfile.dat";
Is this what your code looked like when you ran it, or did something get mangled on the way to being posted here? | [reply] [d/l] |
|
|
Yes, the post was incomplete. Subsequent posts using
open my IN, "<infile.dat";
or similar were correct. | [reply] [d/l] |
|
|
Not quite. This gives an error message:
No such class IN at ./714572.pl line 10, near "open my IN"
syntax error at ./714572.pl line 10, near "my IN,"
Execution of ./714572.pl aborted due to compilation errors.
moritz's code has it right because he uses a lexical filehandle. He also uses the recommended 3-argument form of open and checks its status:
open my $in, '<:raw', 'infile.dat' or die $!;
| [reply] [d/l] [select] |
|
|
Re: Binary conditionals
by JavaFan (Canon) on Sep 30, 2008 at 14:29 UTC
|
One character strings in Perl are still strings; not numbers as in C. So, $buffer == hex ('0x00') would match if, and only if, $buffer == 0, hence, if $buffer contains the character "0". And, as pointed out, when you write it, you write 0x17, aka 23, as digits.
Furthermore, hex('0x00') is redundant. It's equal to 0x00. The same with hex('0x17') which is the same as 0x17.
The right solution has already been mentioned; no need to repeat it. | [reply] [d/l] [select] |
|
|
$ perl -wle '"a" == 0 && print "yes"'
Argument "a" isn't numeric in numeric eq (==) at -e line 1.
yes
So you see that 'a' == 0, and when you have warnings enabled, you also get a warning. | [reply] [d/l] [select] |
|
|
| [reply] |