http://www.perlmonks.org?node_id=917006

andreas1234567 has asked for the wisdom of the Perl Monks concerning the following question:

Honorable Monks,

An application reads binary data from an external system, and saves it using $h = unpack("H*", $b). If I try to reconstruct the binary data with $b = pack("H*", $h), the binary data will sometimes have a trailing null byte. Is it possible to make sure the binary data as it were (i.e. never add the null byte)?

A little code sample to illustrate the problem indicates that is works when input length is even only:
$ cat pack.t use strict; use warnings; use Test::More qw /no_plan/; my @arr = (0 .. 9, 'a' .. 'f'); my $hexdata = q{}; while (@arr) { $hexdata .= shift @arr; my $binary_data = pack("H*", $hexdata); cmp_ok(unpack('H*', $binary_data), 'eq', $hexdata); } __END__ $ perl pack.t not ok 1 # Failed test at pack.t line 11. # got: '00' # expected: '0' ok 2 not ok 3 # Failed test at pack.t line 11. # got: '0120' # expected: '012' ok 4 not ok 5 # Failed test at pack.t line 11. # got: '012340' # expected: '01234' ok 6 not ok 7 # Failed test at pack.t line 11. # got: '01234560' # expected: '0123456' ok 8 not ok 9 # Failed test at pack.t line 11. # got: '0123456780' # expected: '012345678' ok 10 not ok 11 # Failed test at pack.t line 11. # got: '0123456789a0' # expected: '0123456789a' ok 12 not ok 13 # Failed test at pack.t line 11. # got: '0123456789abc0' # expected: '0123456789abc' ok 14 not ok 15 # Failed test at pack.t line 11. # got: '0123456789abcde0' # expected: '0123456789abcde' ok 16 1..16 # Looks like you failed 8 tests of 16.
--
No matter how great and destructive your problems may seem now, remember, you've probably only seen the tip of them. [1]

Replies are listed 'Best First'.
Re: Reconstruct binary data saved with unpack("H*", $b)
by Anonymous Monk on Jul 27, 2011 at 12:41 UTC
    I think the solution is to use u template (uuencoding)

    The problem with your sample data is it doesn't come in pairs -- this is where the null is coming from, its padding -- H* demands pairs

Re: Reconstruct binary data saved with unpack("H*", $b)
by ikegami (Patriarch) on Jul 27, 2011 at 19:27 UTC

    Unless your ok with just using chop on the result — at which point it will only work if the input length is odd — it is impossible to recreate your original data since multiple inputs encode identically.

    $ perl -e'print pack "H*", "abc";' | od -t x1 0000000 ab c0 0000002 $ perl -e'print pack "H*", "abc0";' | od -t x1 0000000 ab c0 0000002

    If you don't care about preserving leading zeroes, you can use

    my $bin = pack("H*", ( length($hex) % 2 ? '0' : '' ).$hex); ... ( my $hex = unpack('H*', $bin) ) =~ s/^0+(?!\z)//;

    If you don't care about preserving leading zeroes, you can use

    my $bin = pack("H*", "".reverse $hex); ... ( my $hex = reverse unpack('H*', $bin) ) =~ s/^0+(?!\z)//;

    If you do care about preserving leading zeroes, you can use

    my $bin = pack("NH*", length($hex), $hex) ... my ($length, $hex) = unpack('NH*', $bin); substr($hex, $length, length($hex), '');