Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?

convert hex to char fast

by Anonymous Monk
on Mar 30, 2010 at 15:50 UTC ( #831885=perlquestion: print w/ replies, xml ) Need Help??
Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi monks, I'm looking for a fast way to convert a string of hex values to their ascii char value.

For years I've been using a hash map to store the hex correspondents, and a regex to replace them, but performance is a little crappy for large, say 1MB+, strings. This is what I have now:

# the conversion table 

my %table = ( '41' => 'A', '42' => 'B' ...);

#   (actually I create it with a one liner, 
#       but I'll spell it out here for simplicity)

my $input = '4142A0B1';  # usually very large
$input =~ s/(..)/$table{$1}/g;  # convert it
print OUTFILE $input;  # print converted to file

Any ideas on how to improve this? Using pack or unpack, for instance? The problem is that I can't come up with a good string-to-string unpack sequence.
I appreciate any pointers on optimizing this.


Replies are listed 'Best First'.
Re: convert hex to char fast
by BrowserUk (Pope) on Mar 30, 2010 at 15:59 UTC


    [0] Perl> print pack 'H*', '4142A0B1';; ABá▒ ## The last character has been mangled by PM

    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.
Re: convert hex to char fast
by ikegami (Pope) on Mar 30, 2010 at 16:29 UTC

    There is no ASCII character A0 or B1. If the data is arbitrary bytes, then the following will do:

    pack('H*', '4142A0B1')

    If the data is actually text (as implied by "ASCII"), you'll need to determine the actual encoding used and use

    decode($enc, pack('H*', '4142A0B1'))

    (The decode step can be skipped for iso-8859-1.)

    For example,

    use strict; use warnings; use open ':std', ':locale'; use Encode qw( decode ); for my $enc (qw( ASCII cp850 cp1252 iso-8859-1 UTF-8 )) { my $s = decode($enc, pack('H*', '4142A0B1'), sub { "?" }); printf("%-11s %s\n", "$enc:", $s); }
    ASCII:      AB??
    cp850:      ABá▒   Common "western" code page for Windows console
    cp1252:     AB ±   Common "western" code page for Windows gui apps
    iso-8859-1: AB ±   Common "western" unix encoding
    UTF-8:      AB??

    Note that cp1252 and iso-8859-1 are not equivalent despite producing the same output in this situation.

      Wow, perfect, pack('H*, $input) gives it a 600% performance increase over my regex.

      Thanks monks, I'm in nirvana now.


Re: convert hex to char fast
by almut (Canon) on Mar 30, 2010 at 15:57 UTC


    my $input = '4142A0B1'; print unpack("a*", pack("H*", $input)); # "AB ±"

    update: actually, the unpack isn't even needed, as the result of the pack already is a byte string...

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://831885]
Approved by toolic
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others avoiding work at the Monastery: (4)
As of 2016-07-24 20:56 GMT
Find Nodes?
    Voting Booth?
    What is your favorite alternate name for a (specific) keyboard key?

    Results (221 votes). Check out past polls.