in reply to Convert binary file to ascii

Once you've read the data from the binmoded file, use this:

Update: added join for commas.

print join ',', map{ sprintf '0x%04x', $_ } unpack 'v*', $bin;; 0x0002 0x0000 0xfff7 0xfff4

Depending which way you're going big- to little-endian or vice versa, you might need to swap 'v*' for 'n*'. See pack for details.


Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
"Too many [] have been sedated by an oppressive environment of political correctness and risk aversion."

Replies are listed 'Best First'.
Re^2: Convert binary file to ascii
by richz (Beadle) on Jun 22, 2007 at 19:13 UTC
    I want to print a newline after every 8 values. Is there any better way of doing this with your method besides the following?

    @converted_list = map{sprintf '0x%04x', $_} unpack ('v*', $line); foreach $sample (@converted_list) { print OUTFILE "$sample, "; $ctr += 1; if (($ctr % 8) == 0) { print OUTFILE "\n"; $ctr = 0; } }

      Probably the easiest way would be to set $/ = \16 so that you read the file in 16 bytes chunks.

      Ie. $/ = \16; while( my $line = <INFILE> ) { willresult in $line containing 16 bytes each time, which will give you your 8 values per output line.

      Simplistically, that make the program something like:

      #! perl -lw use strict; ## Note the -l above which makes print add newlines. open IN, '<:raw:perlio', $ARGV[0] or die $!; open OUT, '>', 'junk.out' or die $!; $/ = \16; ## read 16 bytes at a time; print join ',', map{ sprintf '0x%04x', $_ } unpack 'v*', $_ while <IN> +; close OUT; close IN;

      If there was (still) some way to binmode *ARGV, it could be reduced to a one-liner:

      perl -nle"BEGIN{$/=\16}print join',',map{sprintf'0x%04x',$_}unpack'v*' +,$_" binfile >outfile

      but without binmode, that fails if the file contains a ^Z (control-Z; ascii 26) character.

      Or you can go the other way and 'PBP-up' the above.


      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.

      Well, the $ctr = 0 doesn't do anything useful, and the $ctr += 1 could be merged into the if conditional.

      my @converted_list = map { sprintf('0x%04x', $_) } unpack('v*', $line) +; my $ctr; foreach (@converted_list) { print OUTFILE "$_, "; print OUTFILE "\n" unless ++$ctr % 8; }

      You could merge of all that together if you so desired, but that's probably a bit odd.

      my $ctr; print map { ++$ctr % 8 ? "$_, " : "$_\n" } map { sprintf('0x%04x', $_) } unpack('v*', $line);

      The simplest solution is probably to omit the counter altogether by only reading in 16 bytes at a time. As a bonus, it doesn't leave trailing comma when the file isn't an exact multiple of 16 bytes long.

      # Each line has 8 16-bit words, so 16 bytes. local $/ = \16; while (<INFILE>) { print join ', ', map { sprintf('0x%04x', $_) } unpack('v*', $_); print("\n"); }
Re^2: Convert binary file to ascii
by richz (Beadle) on Jun 22, 2007 at 19:24 UTC
    There is a problem I am running into, and that is that if there is a byte with the value "0a" in the binary file, it is not making it through the conversion process above. I guess something thinks it is a newline. Any idea on how to address that?

    Edit: Upon reading ikegami's reply above, this may have to do with the field record separator, which I just learned about from ikegami's post, i.e. $/.

      That makes no sense. Nothing in the snippet I posted will care, or even notice whether there is an '0a' character in the data it is processing.

      The only time characters get 'converted' is of the file is read with CRLF translation in effect, which it won't be if you have binmoded the file as you did in the OP (and as I mentioned above.


      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.
        I am using binmode as in the OP, but I am seeing some strange behavior. With one of my input files it did skip "0a" bytes. I created a new test file with some "0a" bytes, but with this file it worked correctly, not skipping the "0a" bytes as you suggested. I am doing more investigation to see what's really going on.