in reply to Binary conditionals

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.

Replies are listed 'Best First'.
Re^2: Binary conditionals
by Fletch (Bishop) on Sep 30, 2008 at 14:30 UTC

    Of course y/\0/\x17/ would be even quicker than the substitution . . .</nit>

    The cake is a lie.
    The cake is a lie.
    The cake is a lie.

Re^2: Binary conditionals
by Illuminatus (Curate) on Sep 30, 2008 at 15:21 UTC
    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.
      Is that needed even though :raw is used? I think that the binmode documentation isn't entirely clear. It says:
      If LAYER is omitted or specified as :raw the filehandle is made suitable for passing binary data.

      That reads as if it made a call to binmode superfluous, but on the other hand it talks about a certain orthogonality between IO layers and binmode HANDLE.

        That reads as if it made a call to binmode superfluous

        You're wrong. Without binmode the file handle is in text mode. With binmode but without specified layer, or with layer "raw", it is in binary (raw) mode. That's not the same thing at all, at least, on platforms other than Unix.

        A call to binmode is not superfluous. Instead, I think forgetting about it is the reason why the OP got corrupted data:

        I know I'm fubar'ing the handling somehow; just don't know how :P

        p.s. to the OP: hex('0x17') is a silly, slow way to do things, if you can just enter a hexadecimal numeric literal: 0x17.

Re^2: Binary conditionals
by bunnym4n (Novice) on Sep 30, 2008 at 18:22 UTC
    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.
      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
        That worked perfectly! Thank you!

      Since only characters are involved you can use tr///:

      while (<$in>) { tr/\x00\x17\x4E\x42\x24\x90/\x17\x00\x42\x4E\x90\x24/; print $out $_; }