Convert a string to number and back to string?

11,104

Solution 1

A string-to-number encoder as one-liner (PHP 5.3 style):

$numbers = implode(array_map(function ($n) { return sprintf('%03d', $n); },
                          unpack('C*', $str)));

It simply converts every byte into its decimal number equivalent, zero-padding it to a fixed length of 3 digits so it can be unambiguously converted back.

The decoder back to a string:

$str = implode(array_map('chr', str_split($numbers, 3)));

Example text:

Wörks wíth all ストリングズ
087195182114107115032119195173116104032097108108032227130185227131136227131170227131179227130176227130186

Solution 2

You can't just ORD chars into a string of numbers and expect it to come back because some chars may be on 2 characters and others 3.

For example:

Kang-HO will give you: 10797106103457279

Now how do you know it's not: 10-79-71-0-61-0-34-57-27-9?

You need to either pad all your numbers in 3 number codes and thus get: 107097106103045072079 and then break it apart in blocks of 3 numbers and then ASC them back...

Share:
11,104
Xeoncross
Author by

Xeoncross

PHP, Javascript, and Go Application developer responsible for over 50 open source projects and libraries at https://github.com/xeoncross By default I build Go backends with AngularJS frontends. Thanks to Ionic and Electron this even works for mobile and desktop apps. Bash, PHP, Python, Node.js, and random linux libraries are used for specific tasks because of the size of the ecosystems or libraries for odd jobs.

Updated on June 23, 2022

Comments

  • Xeoncross
    Xeoncross almost 2 years

    I would like to know how I can convert a short ASCII string to a number (int, float, or numeric string). I saw a couple of posts here mentioned perfect hashes which seems like it might be what I need. However, I'm not quite understanding the math for this.

    How could you convert an ASCII string into a sequence of numbers and then back to a string?

    As a side note, breaking a string down into it's ASCII character numbers is easy enough.

    foreach(str_split($string) as $char) $number .= ord($char);
    

    Update

    After more reading I came up with this. However, I'm wondering if there are anyways to shorten the number sequence so it's not quite as long.

    class intnum
    {
        public static $charset = array(
            32 => ' ', 33 => '!', 34 => '"', 35 => '#', 36 => '$',
            37 => '%', 38 => '&', 39 => "'", 40 => '(', 41 => ')',
            42 => '*', 43 => '+', 44 => ',', 45 => '-', 46 => '.',
            47 => '/', 48 => '0', 49 => '1', 50 => '2', 51 => '3',
            52 => '4', 53 => '5', 54 => '6', 55 => '7', 56 => '8',
            57 => '9', 58 => ':', 59 => ';', 60 => '<', 61 => '=',
            62 => '>', 63 => '?', 64 => '@', 65 => 'A', 66 => 'B',
            67 => 'C', 68 => 'D', 69 => 'E', 70 => 'F', 71 => 'G',
            72 => 'H', 73 => 'I', 74 => 'J', 75 => 'K', 76 => 'L',
            77 => 'M', 78 => 'N', 79 => 'O', 80 => 'P', 81 => 'Q',
            82 => 'R', 83 => 'S', 84 => 'T', 85 => 'U', 86 => 'V',
            87 => 'W', 88 => 'X', 89 => 'Y', 90 => 'Z', 91 => '[',
            92 => '\\', 93 => ']', 94 => '^', 95 => '_', 96 => '`',
            97 => 'a', 98 => 'b', 99 => 'c', 100 => 'd', 101 => 'e',
            102 => 'f', 103 => 'g', 104 => 'h', 105 => 'i', 106 => 'j',
            107 => 'k', 108 => 'l', 109 => 'm', 110 => 'n', 111 => 'o',
            112 => 'p', 113 => 'q', 114 => 'r', 115 => 's', 116 => 't',
            117 => 'u', 118 => 'v', 119 => 'w', 120 => 'x', 121 => 'y',
            122 => 'z', 123 => '{', 124 => '|', 125 => '}'
        );
    
        public static function fromNumber($number)
        {
            $string = '';
            while($number)
            {
                $value = substr($number, 0, 2);
                $number = substr($number, 2);
    
                if($value < 32)
                {
                    $value .= substr($number, 0, 1);
                    $number = substr($number, 1);
                }
    
                $string .= self::$charset[ (int) $value];
            }
            return $string;
        }
    
        public static function fromString($string)
        {
            $number = '';
            foreach(str_split($string) as $char) $number .= ord($char);
            return $number;
        }
    }
    
    $string = 'this is my test string to convert';
    
    $number = intnum::fromString($string);
    $string = intnum::fromNumber($number);
    
  • Xeoncross
    Xeoncross over 12 years
    @PhilLello, do you see any way to alter my code above using hex?
  • Xeoncross
    Xeoncross over 12 years
    hmmm, doesn't seem to work with the unicode characters you provided.
  • Gromski
    Gromski over 12 years
    Works fine, as long as you make sure you interpret the result in the same encoding as it was input.
  • Gromski
    Gromski over 12 years
    See codepad.org/wXA9ViFu (written in PHP 5.2 style, since Codepad doesn't run 5.3 yet).
  • Gromski
    Gromski over 12 years
    "11bit words"? 2^11-1 = 127? I think you derailed a little there.
  • Mathieu Dumoulin
    Mathieu Dumoulin over 12 years
    Was about to write it too, 2^11 = 2048... you meant 2^7 but then again, ASCII has 255 characters buddy so it's 2^8...
  • xyzcodeeee
    xyzcodeeee over 2 years
    Works in PHP 8 ?