0

我有一个看起来像这样的字符串(包含数字、句点和破折号):

1372137673.276886940002-19690324617-19694854617-18953258947

由于我只有数字、句点和破折号,我想使用 url 安全(只有数字和字母)编码方案来缩短它。我还需要能够将编码的字符串反转为其原始形式。

我看过base64,但它会增加字符串的大小,这不是我想要的。

我计划用 PHP 和 Javascript 实现这个。

是否有任何现有的方案可以做到这一点?我的主要动机是使上面的字符串更短,结果应该是 URL 安全的。

4

4 回答 4

1

将数字转换为二进制形式,然后 Base64 对其进行编码

于 2013-06-25T11:06:02.887 回答
0

One reasonable attempt would be:

  • break down the string into tokens separated by dashes and dots
  • convert each token to a higher base (36 is a base which you can convert to and from easily from both JS and PHP)
  • join the tokens back together -- both dashes and dots are valid in a URL

However, the "have to do this in JS also" requirement seems a bit suspect -- why does your client-side code have to extract information from URLs which are ultimately under the server's authority? In general URLs should be opaque and when that's not true alarm bells should start ringing.

于 2013-06-25T11:43:57.937 回答
0

要在 javascript 中执行此操作,您需要http://phpjs.org/的帮助:)
我认为我在此脚本中使用的所有 php 函数都可用,例如 您可以调整此代码以获得更小的字符串,位现在很忙,如果我有时间,我肯定会更新这个答案:)bcomp

<?php
  /**
   * This function will encode a larger number to small string
  **/
  function encode( $int = null ) {
    $chars  = 'kwn7uh2qifbj8te9vp64zxcmayrg50ds31';
    $uid    = '';
    while( bccomp( $int, 0, 0) != 0 ) {
      $rem  = bcmod( $int, 34 );
      $int  = bcdiv( bcsub( $int, $rem, 0 ), 34, 0 );
      $uid  = $chars[$rem].$uid;
    }
    return $uid;
  }
  /**
   * This function will decode a string encoded with above function to its original state
  **/
  function decode( $uid = null ) {
    $chars  = 'kwn7uh2qifbj8te9vp64zxcmayrg50ds31';
    $id   = '';
    $len  = strlen( $uid );
    for( $i = $len - 1; $i >= 0; $i-- ) {
      $value  = strpos( $chars, $uid[$i] );
      $id     = bcadd( $id, bcmul( $value, bcpow( 34, ( $len - $i - 1 ) ) ) );
    }
    return $id;
  }
  /**
   * Below function is only for your needs
  **/
  function int_to_str( $str = null, $decode = false ) {
    //$len  = array(); // reserved for further updates :)
    $numbers1 = explode( "-", $str );
    foreach( $numbers1 as &$num1 ) {
      $func = ( $decode ) ? "decode" : "encode";
      $num1 = implode( ".", array_map( $func, explode( ".", $num1 ) ) );
    }
    $numbers1 = implode( "-", $numbers1 );
    return $numbers1;
  }

  // Encode your numbers to short strings
  $str  = int_to_str( "1372137673.276886940002-19690324617-19694854617-18953258947" );
  // Decode your encoded string to its original state
  $int  = int_to_str( $str, true );

  echo $str."<br />";
  echo $int;
?>
于 2013-06-25T11:35:21.353 回答
0

仅仅因为这样做很有趣……它以自定义的 base 64 对字符串进行编码,保持分隔符不变:

function encode_token($digit) {
    if ($digit < 10)
        return (string) $digit;
    if ($digit < 36)
        return chr(ord('A') + ($digit - 10));
    if ($digit < 62)
        return chr(ord('a') + ($digit - 36));
    if ($digit == 62) return ',';
    return '+';
}

function encode_value($value) {
    if (in_array($value, array('.', '-'))) return $value;
    $int = (int) $value;

    $encoded = '';
    while($int) {
        $encoded .= encode_token($int & 0x3F);
        $int >>= 6;
    }
    return $encoded;
}

function encode($string) {
    $values = preg_split(',([\.-]),', $string, -1, PREG_SPLIT_DELIM_CAPTURE);
    $encoded = '';
    foreach($values as $value)
        $encoded .= encode_value($value);
    return $encoded;
}

function decode_token($token) {
    if ($token <= '9') return (int) $token;
    if ($token <= 'Z') return 10 + ord($token) - ord('A');
    if ($token <= 'z') return 36 + ord($token) - ord('a');
    if ($token == ',') return 62;
    return 63;
}

function decode_value($value) {
    if (in_array($value, array('.', '-'))) return $value;

    $decoded = 0;
    for($i = strlen($value) - 1;$i >= 0;$i--) {
        $decoded <<= 6;
        $decoded |= decode_token($value[$i]);
    }
    return $decoded;
}

function decode($string) {
    $values = preg_split(',([\.-]),', $string, -1, PREG_SPLIT_DELIM_CAPTURE);
    $decoded = '';
    foreach($values as $value)
        $decoded .= decode_value($value);
    return $decoded;
}

$string = '1372137673.276886940002-19690324617-19694854617-18953258947';
echo $string . PHP_EOL;
$encoded = encode($string);
echo $encoded . PHP_EOL;
$decoded = decode($encoded);
echo $decoded . PHP_EOL;
于 2013-06-25T11:56:32.700 回答