उचित यूटीएफ -8 एन्कोडेड पात्रों के लिए "\ u00ed" जैसे यूनिकोड एस्केप अनुक्रम को कैसे डीकोड किया जाए?


97

क्या PHP में एक फ़ंक्शन है जो यूनिकोड से बचने के दृश्यों को " \u00ed" से " í" और अन्य सभी समान घटनाओं को डिकोड कर सकता है?

मुझे यहाँ भी ऐसा ही सवाल मिला, लेकिन काम नहीं कर रहा है।

जवाबों:


169

इसे इस्तेमाल करे:

$str = preg_replace_callback('/\\\\u([0-9a-fA-F]{4})/', function ($match) {
    return mb_convert_encoding(pack('H*', $match[1]), 'UTF-8', 'UCS-2BE');
}, $str);

यदि यह UTF-16 आधारित C ​​/ C ++ / Java / Json-style है:

$str = preg_replace_callback('/\\\\u([0-9a-fA-F]{4})/', function ($match) {
    return mb_convert_encoding(pack('H*', $match[1]), 'UTF-8', 'UTF-16BE');
}, $str);

1
मैं "\ u00ed" कहां डालूं?
डॉकस्टरो

2
@ डॉकस्टरो: नियमित अभिव्यक्ति \uचार हेक्साडेसिमल अंकों के बाद किसी भी क्रम से मेल खाएगी ।
गुमबो

9
यह फ़ंक्शन अनुपूरक वर्णों के साथ सौदा नहीं कर सकता क्योंकि उन्हें UCS-2 में प्रतिनिधित्व नहीं किया जा सकता है।
अर्टफेक्टो

3
@gumbo आप इस फ़ंक्शन को कैसे कॉल या उपयोग करेंगे?
Demodave

2
मुझे अपना रास्ता यहाँ मिला जैसा कि मैंने अपने आउटपुट में \ u00ed किया था, लेकिन मैं json_encode () के साथ आउटपुट को देख रहा था और मज़ेदार रूप से डिफ़ॉल्ट json_encode () पर्याप्त रूप से आउटपुट को कचरा कर देगा ताकि json_nodeode ($ theDict, JSON_PRETTY_PRINT. JSON_UNESCAPEDED_UNICODOD) का उपयोग करें।
टॉम एंडरसन

71
print_r(json_decode('{"t":"\u00ed"}')); // -> stdClass Object ( [t] => í )

44
: यह भी वस्तु आवरण की जरूरत नहीं हैjson_decode('"' . $text . '"')
deceze

3
धन्यवाद। ऐसा लगता है कि मानक वेतन , बल्कि फिर स्वीकृत उत्तर है।
टोडुआ

दिलचस्प बात यह है कि यह स्माइली चेहरों की तरह जटिल संस्थाओं के लिए भी काम करता है ... json_decode('{"t":"\uD83D\uDE0A"}')D
डायनामिकडैन

2
@ आपको इस तथ्य को शामिल करना चाहिए $textजिसमें दोहरे उद्धरण शामिल हो सकते हैं। तो एक संशोधित संस्करण होगा json_decode('"'.str_replace('"', '\\"', $text).'"'):। आपकी मदद के लिए धन्यवाद :-)
यवन


10
$str = '\u0063\u0061\u0074'.'\ud83d\ude38';
$str2 = '\u0063\u0061\u0074'.'\ud83d';

// U+1F638
var_dump(
    "cat\xF0\x9F\x98\xB8" === escape_sequence_decode($str),
    "cat\xEF\xBF\xBD" === escape_sequence_decode($str2)
);

function escape_sequence_decode($str) {

    // [U+D800 - U+DBFF][U+DC00 - U+DFFF]|[U+0000 - U+FFFF]
    $regex = '/\\\u([dD][89abAB][\da-fA-F]{2})\\\u([dD][c-fC-F][\da-fA-F]{2})
              |\\\u([\da-fA-F]{4})/sx';

    return preg_replace_callback($regex, function($matches) {

        if (isset($matches[3])) {
            $cp = hexdec($matches[3]);
        } else {
            $lead = hexdec($matches[1]);
            $trail = hexdec($matches[2]);

            // http://unicode.org/faq/utf_bom.html#utf16-4
            $cp = ($lead << 10) + $trail + 0x10000 - (0xD800 << 10) - 0xDC00;
        }

        // https://tools.ietf.org/html/rfc3629#section-3
        // Characters between U+D800 and U+DFFF are not allowed in UTF-8
        if ($cp > 0xD7FF && 0xE000 > $cp) {
            $cp = 0xFFFD;
        }

        // https://github.com/php/php-src/blob/php-5.6.4/ext/standard/html.c#L471
        // php_utf32_utf8(unsigned char *buf, unsigned k)

        if ($cp < 0x80) {
            return chr($cp);
        } else if ($cp < 0xA0) {
            return chr(0xC0 | $cp >> 6).chr(0x80 | $cp & 0x3F);
        }

        return html_entity_decode('&#'.$cp.';');
    }, $str);
}

धन्यवाद। यह पूरक चरित्र के साथ काम करता है, जैसे कि😍
c00000fd

3

यह HTML के साथ कच्चे UNICODE को बदलने के लिए एक स्लेजहैमर दृष्टिकोण है। मैंने इस समाधान को रखने के लिए कोई अन्य जगह नहीं देखी है, लेकिन मुझे लगता है कि दूसरों को यह समस्या हुई है।

कुछ भी करने से पहले RAW JSON को इस str_replace फ़ंक्शन को लागू करें ।

function unicode2html($str){
    $i=65535;
    while($i>0){
        $hex=dechex($i);
        $str=str_replace("\u$hex","&#$i;",$str);
        $i--;
     }
     return $str;
}

जब तक आप सोचते हैं, तब तक यह नहीं होगा, और यह HTML के साथ किसी भी यूनिकोड को बदल देगा।

निश्चित रूप से इसे कम किया जा सकता है यदि आप यूनिकोड प्रकारों को जानते हैं जो JSON में वापस आ रहे हैं।

उदाहरण के लिए मेरा कोड बहुत सारे तीर और डिंगबैट यूनिकोड हो रहा था। ये 8448 से 11263 के बीच हैं। इसलिए मेरा उत्पादन कोड इस तरह दिखता है:

$i=11263;
while($i>08448){
    ...etc...

आप यहाँ पर यूनिकोड के ब्लॉक देख सकते हैं: http://unicode-table.com/en/ यदि आप जानते हैं कि आप अरबी या टेलीगू का अनुवाद कर रहे हैं या जो भी हो, आप बस उन कोड को बदल सकते हैं, सभी 65,000 को नहीं।

आप इसे सरल एन्कोडिंग में उसी स्लेजहैमर को लागू कर सकते हैं:

 $str=str_replace("\u$hex",chr($i),$str);

1

एक समाधान भी है:
http://www.welefen.com/php-unicode-to-utf8.html

function entity2utf8onechar($unicode_c){
    $unicode_c_val = intval($unicode_c);
    $f=0x80; // 10000000
    $str = "";
    // U-00000000 - U-0000007F:   0xxxxxxx
    if($unicode_c_val <= 0x7F){         $str = chr($unicode_c_val);     }     //U-00000080 - U-000007FF:  110xxxxx 10xxxxxx
    else if($unicode_c_val >= 0x80 && $unicode_c_val <= 0x7FF){         $h=0xC0; // 11000000
        $c1 = $unicode_c_val >> 6 | $h;
        $c2 = ($unicode_c_val & 0x3F) | $f;
        $str = chr($c1).chr($c2);
    } else if($unicode_c_val >= 0x800 && $unicode_c_val <= 0xFFFF){         $h=0xE0; // 11100000
        $c1 = $unicode_c_val >> 12 | $h;
        $c2 = (($unicode_c_val & 0xFC0) >> 6) | $f;
        $c3 = ($unicode_c_val & 0x3F) | $f;
        $str=chr($c1).chr($c2).chr($c3);
    }
    //U-00010000 - U-001FFFFF:  11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
    else if($unicode_c_val >= 0x10000 && $unicode_c_val <= 0x1FFFFF){         $h=0xF0; // 11110000
        $c1 = $unicode_c_val >> 18 | $h;
        $c2 = (($unicode_c_val & 0x3F000) >>12) | $f;
        $c3 = (($unicode_c_val & 0xFC0) >>6) | $f;
        $c4 = ($unicode_c_val & 0x3F) | $f;
        $str = chr($c1).chr($c2).chr($c3).chr($c4);
    }
    //U-00200000 - U-03FFFFFF:  111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
    else if($unicode_c_val >= 0x200000 && $unicode_c_val <= 0x3FFFFFF){         $h=0xF8; // 11111000
        $c1 = $unicode_c_val >> 24 | $h;
        $c2 = (($unicode_c_val & 0xFC0000)>>18) | $f;
        $c3 = (($unicode_c_val & 0x3F000) >>12) | $f;
        $c4 = (($unicode_c_val & 0xFC0) >>6) | $f;
        $c5 = ($unicode_c_val & 0x3F) | $f;
        $str = chr($c1).chr($c2).chr($c3).chr($c4).chr($c5);
    }
    //U-04000000 - U-7FFFFFFF:  1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
    else if($unicode_c_val >= 0x4000000 && $unicode_c_val <= 0x7FFFFFFF){         $h=0xFC; // 11111100
        $c1 = $unicode_c_val >> 30 | $h;
        $c2 = (($unicode_c_val & 0x3F000000)>>24) | $f;
        $c3 = (($unicode_c_val & 0xFC0000)>>18) | $f;
        $c4 = (($unicode_c_val & 0x3F000) >>12) | $f;
        $c5 = (($unicode_c_val & 0xFC0) >>6) | $f;
        $c6 = ($unicode_c_val & 0x3F) | $f;
        $str = chr($c1).chr($c2).chr($c3).chr($c4).chr($c5).chr($c6);
    }
    return $str;
}
function entities2utf8($unicode_c){
    $unicode_c = preg_replace("/\&\#([\da-f]{5})\;/es", "entity2utf8onechar('\\1')", $unicode_c);
    return $unicode_c;
}

1

json मानों को ठीक करें, यह \ {u} से पहले \ "सभी +" में जोड़ देगा

  $item = preg_replace_callback('/"(.+?)":"(u.+?)",/', function ($matches) {
        $matches[2] = preg_replace('/(u)/', '\u', $matches[2]);
            $matches[2] = preg_replace('/(")/', '&quot;', $matches[2]); 
            $matches[2] = json_decode('"' . $matches[2] . '"'); 
            return '"' . $matches[1] . '":"' . $matches[2] . '",';
        }, $item);
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.