Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change

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 all is quiet...

How do I use this? | Other CB clients
Other Users?
Others chilling in the Monastery: (4)
As of 2017-05-27 15:48 GMT
Find Nodes?
    Voting Booth?