Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

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.

Barry

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

    Maybe

    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...

Re: convert hex to char fast
by BrowserUk (Pope) on Mar 30, 2010 at 15:59 UTC

    Voila?

    [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.

      Barry

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others wandering the Monastery: (4)
As of 2014-09-23 04:26 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    How do you remember the number of days in each month?











    Results (210 votes), past polls