ตรวจจับการเข้ารหัสและทำให้ทุกอย่างเป็น UTF-8


304

ฉันอ่านข้อความจำนวนมากจากฟีด RSS ต่างๆและแทรกลงในฐานข้อมูลของฉัน

แน่นอนว่ามีการเข้ารหัสอักขระหลายตัวที่ใช้ในฟีดเช่น UTF-8 และ ISO 8859-1

น่าเสียดายที่บางครั้งมีปัญหากับการเข้ารหัสของข้อความ ตัวอย่าง:

  1. "ß" ใน "Fußball" ควรมีลักษณะเช่นนี้ในฐานข้อมูลของฉัน: "Ÿ" หากเป็น "Ÿ" แสดงว่าถูกต้อง

  2. บางครั้ง "ß" ใน "Fußball" มีลักษณะเช่นนี้ในฐานข้อมูลของฉัน: "ß" แน่นอนว่ามันถูกแสดงอย่างผิด ๆ

  3. ในกรณีอื่น ๆ "ß" จะถูกบันทึกเป็น "ß" - ดังนั้นโดยไม่มีการเปลี่ยนแปลงใด ๆ จากนั้นมันก็จะแสดงผิด

ฉันจะทำอย่างไรเพื่อหลีกเลี่ยงกรณีที่ 2 และ 3

ฉันจะทำให้ทุกอย่างเข้ารหัสเหมือนกันโดยเฉพาะอย่างยิ่ง UTF-8 ได้อย่างไร ฉันต้องใช้utf8_encode()เมื่อใดฉันจะต้องใช้เมื่อใดutf8_decode()(ชัดเจนว่าผลกระทบคืออะไร แต่เมื่อใดฉันต้องใช้ฟังก์ชั่น?) และเมื่อใดที่ฉันต้องใช้อะไรกับอินพุต?

ฉันจะทำให้การเข้ารหัสทุกอย่างเหมือนกันได้อย่างไร บางทีด้วยฟังก์ชั่นmb_detect_encoding()? ฉันสามารถเขียนฟังก์ชันสำหรับสิ่งนี้ได้หรือไม่? ดังนั้นปัญหาของฉันคือ:

  1. ฉันจะค้นหาการเข้ารหัสข้อความที่ใช้ได้อย่างไร
  2. ฉันจะแปลงเป็น UTF-8 ได้อย่างไรการเข้ารหัสแบบเก่าคืออะไร

ฟังก์ชั่นนี้จะใช้งานได้ไหม?

function correct_encoding($text) {
    $current_encoding = mb_detect_encoding($text, 'auto');
    $text = iconv($current_encoding, 'UTF-8', $text);
    return $text;
}

ฉันทดสอบแล้ว แต่ใช้งานไม่ได้ มีอะไรผิดปกติกับมัน?


36
"The" ß "ใน" Fußball "ควรมีลักษณะเช่นนี้ในฐานข้อมูลของฉัน:" Ÿ " ไม่ควรมีลักษณะเหมือนß ตรวจสอบให้แน่ใจว่าการเปรียบเทียบและการเชื่อมต่อของคุณได้รับการตั้งค่าอย่างถูกต้อง มิฉะนั้นการเรียงลำดับและการค้นหาจะทำให้คุณเสีย
แบรดชอว์รวย

5
ฐานข้อมูลของคุณติดตั้งไม่ดี หากคุณต้องการเก็บเนื้อหา Unicode เพียงแค่กำหนดค่าสำหรับสิ่งนั้น ดังนั้นแทนที่จะพยายามแก้ไขปัญหาในรหัส PHP ของคุณคุณควรแก้ไขฐานข้อมูลก่อน
dolmen

2
ใช้: $ from = mb_detect_encoding ($ text); $ text = mb_convert_encoding ($ ข้อความ 'UTF-8', $ จาก);
Informate.it

คำตอบ:


363

หากคุณใช้utf8_encode()กับสตริง UTF-8 แล้วสตริงนั้นจะส่งคืนเอาต์พุต UTF-8 ที่อ่านไม่ออก

ฉันทำฟังก์ชั่นที่จัดการปัญหาทั้งหมดนี้ It's Encoding::toUTF8()เรียกว่า

คุณไม่จำเป็นต้องรู้ว่าการเข้ารหัสสตริงของคุณคืออะไร มันอาจเป็น Latin1 ( ISO 8859-1) , Windows-1252หรือ UTF-8 หรือสตริงอาจมีการผสมกัน Encoding::toUTF8()จะแปลงทุกอย่างเป็น UTF-8

ฉันทำเพราะบริการให้ฟีดข้อมูลทั้งหมดแก่ฉันยุ่งโดยผสม UTF-8 และ Latin1 ในสตริงเดียวกัน

การใช้งาน:

require_once('Encoding.php');
use \ForceUTF8\Encoding;  // It's namespaced now.

$utf8_string = Encoding::toUTF8($utf8_or_latin1_or_mixed_string);

$latin1_string = Encoding::toLatin1($utf8_or_latin1_or_mixed_string);

ดาวน์โหลด:

https://github.com/neitanod/forceutf8

ฉันได้รวมฟังก์ชั่นอื่นEncoding::fixUFT8()ซึ่งจะแก้ไขสตริง UTF-8 ทุกอันที่อ่านไม่ออก

การใช้งาน:

require_once('Encoding.php');
use \ForceUTF8\Encoding;  // It's namespaced now.

$utf8_string = Encoding::fixUTF8($garbled_utf8_string);

ตัวอย่าง:

echo Encoding::fixUTF8("Fédération Camerounaise de Football");
echo Encoding::fixUTF8("Fédération Camerounaise de Football");
echo Encoding::fixUTF8("FÃÂédÃÂération Camerounaise de Football");
echo Encoding::fixUTF8("Fédération Camerounaise de Football");

จะส่งออก:

Fédération Camerounaise de Football
Fédération Camerounaise de Football
Fédération Camerounaise de Football
Fédération Camerounaise de Football

ผมเคยเปลี่ยนฟังก์ชั่น ( forceUTF8) Encodingในครอบครัวของฟังก์ชั่นคงที่ในระดับที่เรียกว่า Encoding::toUTF8()ฟังก์ชั่นใหม่คือ


1
ถ้าคุณดูรหัส fixUTF8 ก็แค่เรียก forceUTF8 ซ้ำแล้วซ้ำอีกจนกว่าสตริงจะถูกส่งคืนไม่เปลี่ยนแปลง One call to fixUTF8 () ใช้เวลาอย่างน้อยสองครั้งในการเรียกไปยัง forceUTF8 () ดังนั้นจึงมีประสิทธิภาพน้อยกว่ามาก ฉันสร้าง fixUTF8 () เพียงเพื่อสร้างโปรแกรมบรรทัดคำสั่งที่จะแก้ไขไฟล์ "เข้ารหัสเสียหาย" แต่ในสภาพแวดล้อมจริงไม่ค่อยจำเป็น
Sebastián Grignoli

3
สิ่งนี้จะแปลงอักขระที่ไม่ใช่ UTF8 เป็น UTF8 ได้อย่างไรโดยไม่ทราบว่าการเข้ารหัสอักขระที่ไม่ถูกต้องจะเริ่มต้นอย่างไร
philfreo

4
มันถือว่า ISO-8859-1 คำตอบนี้บอกไปแล้ว ข้อแตกต่างระหว่าง forceUTF8 () และ utf8_encode () คือ forceUTF8 () รู้จักตัวอักษร UTF8 และทำให้ไม่เปลี่ยนแปลง
Sebastián Grignoli

28
"คุณไม่จำเป็นต้องรู้ว่าการเข้ารหัสสตริงของคุณคืออะไร" - ฉันไม่เห็นด้วยมาก การคาดเดาและการพยายามอาจใช้งานได้ แต่คุณจะเจอกรณีขอบไม่ช้าไม่ช้า
หลอกลวง

4
ฉันเห็นด้วยอย่างยิ่ง ในความเป็นจริงฉันไม่ได้ตั้งใจจะบอกว่าตามกฎทั่วไปเพียงแค่อธิบายว่าชั้นเรียนนี้อาจช่วยคุณได้ถ้านั่นเป็นสถานการณ์ที่คุณจะพบว่าตัวเองเจอ
Sebastián Grignoli

74

ก่อนอื่นคุณต้องตรวจสอบว่ามีการใช้การเข้ารหัสใดบ้าง ในขณะที่คุณกำลังแยก RSS ฟีด (อาจจะผ่านทาง HTTP) คุณควรอ่านการเข้ารหัสจากcharsetพารามิเตอร์ของข้อมูลส่วนหัวของContent-Type HTTP ถ้ามันไม่ได้เป็นปัจจุบันอ่านการเข้ารหัสจากencodingแอตทริบิวต์ของคำสั่งประมวลผล XML หากยังขาดอยู่ให้ใช้ UTF-8 ตามที่กำหนดในสเป


แก้ไข    นี่คือสิ่งที่ฉันอาจจะทำ:

ฉันจะใช้cURLเพื่อส่งและรับการตอบกลับ ที่ช่วยให้คุณตั้งค่าฟิลด์ส่วนหัวเฉพาะและดึงส่วนหัวการตอบกลับได้ หลังจากดึงการตอบสนองคุณจะต้องแยกการตอบสนอง HTTP และแยกออกเป็นส่วนหัวและร่างกาย ส่วนหัวควรมีContent-Typeฟิลด์ส่วนหัวที่มีประเภท MIME และ (หวังว่า) charsetพารามิเตอร์ที่มีการเข้ารหัส / ชุดอักขระเช่นกัน ถ้าไม่เราจะวิเคราะห์ XML PI สำหรับการมีencodingแอตทริบิวต์และรับการเข้ารหัสจากที่นั่น หากยังขาดหายไปข้อมูลจำเพาะ XML จะกำหนดให้ใช้ UTF-8 เป็นการเข้ารหัส

$url = 'http://www.lr-online.de/storage/rss/rss/sport.xml';

$accept = array(
    'type' => array('application/rss+xml', 'application/xml', 'application/rdf+xml', 'text/xml'),
    'charset' => array_diff(mb_list_encodings(), array('pass', 'auto', 'wchar', 'byte2be', 'byte2le', 'byte4be', 'byte4le', 'BASE64', 'UUENCODE', 'HTML-ENTITIES', 'Quoted-Printable', '7bit', '8bit'))
);
$header = array(
    'Accept: '.implode(', ', $accept['type']),
    'Accept-Charset: '.implode(', ', $accept['charset']),
);
$encoding = null;
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HEADER, true);
curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
$response = curl_exec($curl);
if (!$response) {
    // error fetching the response
} else {
    $offset = strpos($response, "\r\n\r\n");
    $header = substr($response, 0, $offset);
    if (!$header || !preg_match('/^Content-Type:\s+([^;]+)(?:;\s*charset=(.*))?/im', $header, $match)) {
        // error parsing the response
    } else {
        if (!in_array(strtolower($match[1]), array_map('strtolower', $accept['type']))) {
            // type not accepted
        }
        $encoding = trim($match[2], '"\'');
    }
    if (!$encoding) {
        $body = substr($response, $offset + 4);
        if (preg_match('/^<\?xml\s+version=(?:"[^"]*"|\'[^\']*\')\s+encoding=("[^"]*"|\'[^\']*\')/s', $body, $match)) {
            $encoding = trim($match[1], '"\'');
        }
    }
    if (!$encoding) {
        $encoding = 'utf-8';
    } else {
        if (!in_array($encoding, array_map('strtolower', $accept['charset']))) {
            // encoding not accepted
        }
        if ($encoding != 'utf-8') {
            $body = mb_convert_encoding($body, 'utf-8', $encoding);
        }
    }
    $simpleXML = simplexml_load_string($body, null, LIBXML_NOERROR);
    if (!$simpleXML) {
        // parse error
    } else {
        echo $simpleXML->asXML();
    }
}

ขอบคุณ มันจะง่าย แต่มันจะใช้งานได้จริงเหรอ? มักจะมีการเข้ารหัสที่ผิดที่กำหนดในส่วนหัว HTTP หรือในคุณสมบัติของ XML
caw

25
อีกครั้ง: นั่นไม่ใช่ปัญหาของคุณ มีการกำหนดมาตรฐานเพื่อหลีกเลี่ยงปัญหาดังกล่าว หากคนอื่นไม่ติดตามพวกเขานั่นเป็นปัญหาของพวกเขาไม่ใช่ของคุณ
Gumbo

ตกลงฉันคิดว่าในที่สุดคุณก็เชื่อฉันในตอนนี้ :)
caw

ขอบคุณสำหรับรหัส แต่ทำไมไม่ใช้เพียงแค่นี้ paste.bradleygill.com/index.php?paste_id=9651รหัสของคุณซับซ้อนกว่านี้มากดีกว่า
caw

ก่อนอื่นคุณต้องทำสองคำขอหนึ่งคำขอสำหรับส่วนหัว HTTP และอีกหนึ่งคำขอสำหรับข้อมูล ประการที่สองคุณกำลังมองหาลักษณะใด ๆcharset=และencoding=และไม่เพียง แต่ในตำแหน่งที่เหมาะสม และประการที่สามคุณไม่ได้ตรวจสอบว่าการเข้ารหัสที่ประกาศนั้นได้รับการยอมรับหรือไม่
Gumbo

39

การตรวจจับการเข้ารหัสนั้นยาก

mb_detect_encodingทำงานโดยการเดาตามจำนวนผู้สมัครที่คุณผ่านมัน ในการเข้ารหัสบางลำดับไบต์บางอย่างไม่ถูกต้องดังนั้นจึงสามารถแยกความแตกต่างระหว่างผู้สมัครต่าง ๆ น่าเสียดายที่มีการเข้ารหัสจำนวนมากซึ่งไบต์เดียวกันนั้นใช้ได้ (แต่แตกต่างกัน) ในกรณีเหล่านี้ไม่มีวิธีตรวจสอบการเข้ารหัส คุณสามารถใช้ตรรกะของคุณเองเพื่อคาดเดาในกรณีเหล่านี้ ตัวอย่างเช่นข้อมูลที่มาจากไซต์ญี่ปุ่นอาจมีแนวโน้มที่จะเข้ารหัสภาษาญี่ปุ่นมากกว่า

ตราบใดที่คุณจะจัดการกับภาษายุโรปตะวันตกสามการเข้ารหัสที่สำคัญที่จะต้องพิจารณาutf-8, และiso-8859-1 cp-1252เนื่องจากสิ่งเหล่านี้เป็นค่าเริ่มต้นสำหรับหลาย ๆ แพลตฟอร์มจึงมีแนวโน้มที่จะรายงานอย่างผิดพลาด เช่น. หากคนใช้การเข้ารหัสที่แตกต่างกันพวกเขามีแนวโน้มที่จะเปิดเผยเกี่ยวกับเรื่องนี้เพราะซอฟต์แวร์ของพวกเขาจะทำลายบ่อยมาก ดังนั้นกลยุทธ์ที่ดีคือการเชื่อถือผู้ให้บริการเว้นแต่จะมีการรายงานการเข้ารหัสเป็นหนึ่งในสามรายการดังกล่าว คุณควรตรวจสอบอีกครั้งว่าใช้งานได้จริงmb_check_encoding(โปรดทราบว่าการใช้งานนั้นไม่เหมือนกับการใช้งาน - อินพุตเดียวกันอาจใช้ได้กับการเข้ารหัสหลายครั้ง) หากเป็นหนึ่งในนั้นคุณสามารถใช้mb_detect_encodingเพื่อแยกความแตกต่างระหว่างพวกเขา โชคดีที่ค่อนข้างแน่นอน UTF-8,ISO-8859-1,WINDOWS-1252คุณเพียงแค่ต้องใช้ที่เหมาะสมตรวจสอบลำดับซึ่งเป็น

เมื่อคุณตรวจพบการเข้ารหัสคุณจะต้องแปลงเป็นการแสดงภายในของคุณ ( UTF-8เป็นทางเลือกเดียวที่มีสติ) ฟังก์ชันutf8_encodeแปลงISO-8859-1เป็นUTF-8ดังนั้นจึงสามารถใช้ได้กับประเภทอินพุตเฉพาะนั้นเท่านั้น สำหรับการเข้ารหัสอื่น ๆ mb_convert_encodingการใช้งาน


ขอบคุณมาก! มีอะไรดีกว่า: mb-convert-encoding () หรือ iconv () ฉันไม่รู้ว่าความแตกต่างคืออะไร ใช่ฉันจะต้องแยกวิเคราะห์ภาษายุโรปตะวันตกโดยเฉพาะอังกฤษเยอรมันและฝรั่งเศส
caw

7
ฉันเพิ่งเห็น: mb-detect-encoding () ไม่ไร้ประโยชน์ รองรับเฉพาะ UTF-8, UTF-7, ASCII, EUC-JP, SJIS, eucJP-win, SJIS-win, JIS และ ISO-2022-JP ไม่รองรับสิ่งที่สำคัญที่สุดสำหรับฉัน ISO-8859-1 และ WINDOWS-1252 ดังนั้นฉันไม่สามารถใช้ mb-detect-encoding ()
caw

1
ของฉันคุณพูดถูก ไม่นานมานี้ฉันใช้ไปแล้ว คุณจะต้องเขียนรหัสตรวจจับของคุณเองหรือใช้ยูทิลิตี้ภายนอก สามารถกำหนด UTF-8 ได้อย่างน่าเชื่อถือเนื่องจากชุดลำดับการหลบหนีของมันมีลักษณะที่ค่อนข้าง wp-1252 และ iso-8859-1 สามารถแยกได้เนื่องจาก wp-1252 อาจมีจำนวนไบต์ที่ผิดกฎหมายใน iso-8859-1 ใช้ Wikipedia เพื่อรับรายละเอียดหรือดูในส่วนความเห็นของ php.net ภายใต้ฟังก์ชั่นต่างๆที่เกี่ยวข้องกับชุดอักขระ
troelskn

ฉันคิดว่าคุณสามารถแยกแยะการเข้ารหัสที่แตกต่างกันเมื่อคุณดูแบบฟอร์มที่มีการร้องเพลงพิเศษเกิดขึ้น: เยอรมัน "ß" โผล่ออกมาในรูปแบบต่าง ๆ : บางครั้ง "Ÿ", บางครั้ง "ß" และบางครั้ง "ß" ทำไม?
caw

ใช่ แต่คุณต้องรู้เนื้อหาของสายอักขระก่อนที่จะทำการเปรียบเทียบและการเอาชนะจุดประสงค์นั้นเป็นสิ่งแรก ßเยอรมันปรากฏแตกต่างกันเนื่องจากมีค่าแตกต่างกันในการเข้ารหัสที่แตกต่างกัน อักขระ Somce เกิดขึ้นในลักษณะเดียวกันในการเข้ารหัสที่แตกต่างกัน (เช่นอักขระทั้งหมดใน ascii charset จะถูกเข้ารหัสในลักษณะเดียวกันใน utf-8, iso-8859- * และ wp-1252) ดังนั้นตราบใดที่คุณใช้ แค่ตัวละครพวกนั้นพวกมันก็เหมือนกันหมด นั่นเป็นเหตุผลที่พวกเขาบางครั้งเรียกว่าเข้ากันได้กับ ASCII
troelskn

14

จริงๆวิธีที่ดีที่จะใช้isUTF8ฟังก์ชั่สามารถพบได้ในphp.net :

function isUTF8($string) {
    return (utf8_encode(utf8_decode($string)) == $string);
}

16
น่าเสียดายนี่ใช้งานได้เมื่อสตริงประกอบด้วยอักขระที่รวมอยู่ใน ISO-8859-1 เท่านั้น แต่สิ่งนี้สามารถใช้งานได้: @iconv ('utf-8', 'utf-8 // IGNORE', $ str) == $ str
Christian Davén

@ คริสเตียน: แน่นอนว่าเป็นสิ่งที่ผู้เขียน MySQL ประสิทธิภาพสูงแนะนำเช่นกัน
Alix Axel

1
มันทำงานไม่ถูกต้อง: echo (int) isUTF8 ('z'); # 1 echo (int) isUTF8 (NULL); # 1
Yousha Aleayoub

1
แม้ว่าจะไม่สมบูรณ์แบบ แต่ฉันคิดว่านี่เป็นวิธีที่ดีในการใช้เช็ค UTF-8 อย่างย่อ
Mateng

1
mb_check_encoding($string, 'UTF-8')
หลอกลวง

13

แผ่นชีทนี้แสดงรายการคำเตือนทั่วไปที่เกี่ยวข้องกับการจัดการ UTF-8 ใน PHP: http://developer.loftdigital.com/blog/php-utf-8-cheatsheet

ฟังก์ชั่นนี้ตรวจจับอักขระหลายไบต์ในสตริงอาจเป็นประโยชน์ ( แหล่งที่มา ):


function detectUTF8($string)
{
    return preg_match('%(?:
        [\xC2-\xDF][\x80-\xBF]             # non-overlong 2-byte
        |\xE0[\xA0-\xBF][\x80-\xBF]        # excluding overlongs
        |[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte
        |\xED[\x80-\x9F][\x80-\xBF]        # excluding surrogates
        |\xF0[\x90-\xBF][\x80-\xBF]{2}     # planes 1-3
        |[\xF1-\xF3][\x80-\xBF]{3}         # planes 4-15
        |\xF4[\x80-\x8F][\x80-\xBF]{2}     # plane 16
        )+%xs', 
    $string);
}


2
ฉันคิดว่ามันทำงานไม่ถูกต้อง: echo detectUTF8 ('3٣3'); # 1
Yousha Aleayoub

10

หัวน้อยขึ้น คุณบอกว่าควรจะแสดง "ß" เป็น "Ÿ" ในฐานข้อมูลของคุณ

อาจเป็นเพราะคุณกำลังใช้ฐานข้อมูลที่มีการเข้ารหัสอักขระละติน -1 หรืออาจเป็นเพราะการเชื่อมต่อ PHP-MySQL ของคุณตั้งอยู่ผิดนี่คือ P เชื่อว่า MySQL ของคุณตั้งค่าให้ใช้ UTF-8 ดังนั้นมันจึงส่งข้อมูลเป็น UTF-8 แต่ MySQL ของคุณเชื่อว่า PHP กำลังส่งข้อมูลที่เข้ารหัสตาม ISO 8859-1 ดังนั้นจึงอาจลองเข้ารหัสข้อมูลที่ส่งเป็น UTF-8 อีกครั้งทำให้เกิดปัญหาประเภทนี้อีกครั้ง

ลองดูที่mysql_set_charset มันอาจช่วยคุณได้


4

ลักษณะการเข้ารหัสของคุณเช่นคุณเข้ารหัสเป็น UTF-8 สองครั้ง ; นั่นคือจากการเข้ารหัสอื่น ๆ ไปเป็น UTF-8 และอีกครั้งใน UTF-8 ราวกับว่าคุณมี ISO 8859-1 แปลงจาก ISO 8859-1 เป็น UTF-8 และใช้สตริงใหม่เป็น ISO 8859-1 สำหรับการแปลงอื่นเป็น UTF-8

นี่คือรหัสเทียมบางส่วนของสิ่งที่คุณทำ:

$inputstring = getFromUser();
$utf8string = iconv($current_encoding, 'utf-8', $inputstring);
$flawedstring = iconv($current_encoding, 'utf-8', $utf8string);

คุณควรลอง:

  1. ตรวจจับการเข้ารหัสโดยใช้mb_detect_encoding()หรือสิ่งที่คุณต้องการใช้
  2. ถ้าเป็น UTF-8 ให้แปลงเป็น ISO 8859-1 และทำซ้ำขั้นตอนที่ 1
  3. ในที่สุดแปลงกลับเป็น UTF-8

มีการสันนิษฐานว่าในการแปลง "กลาง" คุณใช้ ISO 8859-1 หากคุณใช้ Windows-1252 ให้แปลงเป็น Windows-1252 (latin1) การเข้ารหัสต้นฉบับไม่สำคัญ สิ่งที่คุณใช้ในข้อบกพร่องการแปลงครั้งที่สองคือ

นี่คือการคาดเดาของฉันในสิ่งที่เกิดขึ้น; มีอย่างน้อยมากที่คุณสามารถทำได้เพื่อให้ได้สี่ไบต์แทนหนึ่งส่วนขยาย ASCII ไบต์

ภาษาเยอรมันยังใช้ISO 8859-2และWindows-1250 (ละติน -2)


3

สิ่งที่น่าสนใจเกี่ยวกับmb_detect_encodingและmb_convert_encodingลำดับของการเข้ารหัสที่คุณแนะนำนั้นมีความสำคัญ:

// $input is actually UTF-8

mb_detect_encoding($input, "UTF-8", "ISO-8859-9, UTF-8");
// ISO-8859-9 (WRONG!)

mb_detect_encoding($input, "UTF-8", "UTF-8, ISO-8859-9");
// UTF-8 (OK)

ดังนั้นคุณอาจต้องการใช้คำสั่งเฉพาะเมื่อระบุการเข้ารหัสที่คาดไว้ อย่างไรก็ตามโปรดจำไว้ว่านี่ไม่สามารถป้องกันความผิดพลาดได้


2
สิ่งนี้เกิดขึ้นเพราะ ISO-8859-9 ในทางปฏิบัติจะยอมรับอินพุตแบบไบนารี่ใด ๆ เช่นเดียวกันสำหรับ Windows-1252 และเพื่อน ๆ คุณต้องทดสอบการเข้ารหัสก่อนที่จะไม่สามารถรับอินพุตได้
Mikko Rantalainen

@MikkoRantalainen ใช่ฉันเดาว่าส่วนนี้ของเอกสารบอกว่าคล้ายกัน: php.net/manual/en/function.mb-detect-order.php#example-2985
Halil Özgür

เมื่อพิจารณาว่าสเป็ค WHATWG HTML กำหนด Windows 1252 เป็นการเข้ารหัสเริ่มต้นมันน่าจะปลอดภัยพอที่จะสันนิษฐานif ($input_is_not_UTF8) $input_is_windows1252 = true;ได้ ดูเพิ่มเติมที่: html.spec.whatwg.org/multipage/ …
Mikko Rantalainen

3

คุณต้องทดสอบชุดอักขระของอินพุตเนื่องจากการตอบกลับอาจมีรหัสที่แตกต่างกัน

ฉันบังคับให้ส่งเนื้อหาทั้งหมดไปยัง UTF-8 โดยทำการตรวจจับและแปลโดยใช้ฟังก์ชั่นต่อไปนี้:

function fixRequestCharset()
{
  $ref = array(&$_GET, &$_POST, &$_REQUEST);
  foreach ($ref as &$var)
  {
    foreach ($var as $key => $val)
    {
      $encoding = mb_detect_encoding($var[$key], mb_detect_order(), true);
      if (!$encoding)
        continue;
      if (strcasecmp($encoding, 'UTF-8') != 0)
      {
        $encoding = iconv($encoding, 'UTF-8', $var[$key]);
        if ($encoding === false)
          continue;
        $var[$key] = $encoding;
      }
    }
  }
}

รูทีนนั้นจะเปลี่ยนตัวแปร PHP ทั้งหมดที่มาจากรีโมตโฮสต์เป็น UTF-8

หรือละเว้นค่าหากไม่สามารถตรวจพบหรือแปลงการเข้ารหัส

คุณสามารถปรับแต่งมันตามความต้องการของคุณ

เพียงแค่เรียกใช้ก่อนที่จะใช้ตัวแปร


จุดประสงค์ในการใช้ mb_detect_order () โดยไม่ผ่านรายการการเข้ารหัสคืออะไร
giorgio79

วัตถุประสงค์คือเพื่อส่งคืนอาเรย์ที่กำหนดค่าไว้ของการเข้ารหัสที่กำหนดไว้ใน php.ini ที่ใช้ สิ่งนี้จำเป็นต้องใช้โดย mb_detect_encoding เพื่อเติมพารามิเตอร์ที่สาม
cavila

2

การทำงานออกเข้ารหัสอักขระของฟีด RSS ดูเหมือนว่าจะมีความซับซ้อน แม้แต่หน้าเว็บปกติก็มักจะละเว้นหรือโกหกการเข้ารหัส

ดังนั้นคุณสามารถลองใช้วิธีที่ถูกต้องในการตรวจจับการเข้ารหัสจากนั้นถอยกลับไปที่การตรวจจับอัตโนมัติบางรูปแบบ (คาดเดา)


ฉันไม่ต้องการอ่านการเข้ารหัสจากข้อมูลฟีด ดังนั้นจึงเท่ากับว่าข้อมูลฟีดไม่ถูกต้อง ฉันต้องการตรวจจับการเข้ารหัสจากข้อความ
caw

@ marco92w: ไม่ใช่ปัญหาของคุณถ้าการเข้ารหัสที่ประกาศนั้นผิด มาตรฐานยังไม่ได้รับการจัดตั้งขึ้นเพื่อความสนุกสนาน
Gumbo

1
@Gumbo: แต่ถ้าคุณกำลังทำงานในโลกแห่งความเป็นจริงคุณจะต้องสามารถจัดการกับสิ่งต่าง ๆ เช่นการเข้ารหัสที่ไม่ถูกต้อง ปัญหาคือว่ามันยากมากที่จะเดา (ถูกต้อง) การเข้ารหัสเพียงแค่จากข้อความบางส่วน มาตรฐานนั้นยอดเยี่ยม แต่มีจำนวนมาก (มากที่สุด) ของหน้าเว็บ / ฟีดที่ออกมาไม่ตรงกับพวกเขา
46432 Kevin ORourke

@Kevin ORourke: ถูกต้อง นั่นคือปัญหาของฉัน @Gumbo: ใช่มันเป็นปัญหาของฉัน ฉันต้องการอ่านฟีดและรวมเข้าด้วยกัน ดังนั้นฉันต้องแก้ไขการเข้ารหัสที่ผิด
caw

@ marco92w: แต่คุณไม่สามารถแก้ไขการเข้ารหัสได้หากคุณไม่รู้การเข้ารหัสที่ถูกต้องและการเข้ารหัสปัจจุบัน และนั่นคือสิ่งที่เป็นcharset/ encodingประกาศถ้า: อธิบายการเข้ารหัสข้อมูลที่ถูกเข้ารหัสใน.
ต้นกระเจี๊ยบ

2

ฉันรู้ว่านี่เป็นคำถามที่เก่ากว่า แต่ฉันคิดว่าคำตอบที่มีประโยชน์ไม่เคยเจ็บปวด ฉันมีปัญหาในการเข้ารหัสระหว่างแอปพลิเคชันเดสก์ท็อป SQLite และ GET / POST บางตัวจะอยู่ใน UTF-8 บางตัวจะอยู่ใน ASCII และโดยพื้นฐานแล้วทุกอย่างจะสับสนเมื่อตัวละครต่างประเทศเข้ามาเกี่ยวข้อง

นี่คือทางออกของฉัน มันขัดตัว GET / POST / REQUEST ของคุณ (ฉันตัดคุกกี้ แต่คุณสามารถเพิ่มได้ถ้าต้องการ) ในการโหลดแต่ละหน้าก่อนประมวลผล มันทำงานได้ดีในส่วนหัว PHP จะส่งคำเตือนหากตรวจไม่พบการเข้ารหัสที่มาโดยอัตโนมัติดังนั้นคำเตือนเหล่านี้จะถูกระงับด้วย @

//Convert everything in our vars to UTF-8 for playing nice with the database...
//Use some auto detection here to help us not double-encode...
//Suppress possible warnings with @'s for when encoding cannot be detected
try
{
    $process = array(&$_GET, &$_POST, &$_REQUEST);
    while (list($key, $val) = each($process)) {
        foreach ($val as $k => $v) {
            unset($process[$key][$k]);
            if (is_array($v)) {
                $process[$key][@mb_convert_encoding($k,'UTF-8','auto')] = $v;
                $process[] = &$process[$key][@mb_convert_encoding($k,'UTF-8','auto')];
            } else {
                $process[$key][@mb_convert_encoding($k,'UTF-8','auto')] = @mb_convert_encoding($v,'UTF-8','auto');
            }
        }
    }
    unset($process);
}
catch(Exception $ex){}

ขอบคุณสำหรับคำตอบ jocull ฟังก์ชั่น mb_convert_encoding () เป็นสิ่งที่เรามีอยู่แล้วใช่ไหม? ;) สิ่งใหม่ในคำตอบของคุณคือลูปสำหรับเปลี่ยนการเข้ารหัสในตัวแปรทั้งหมด
caw

2

ฉันกำลังตรวจสอบหาวิธีการเข้ารหัสตั้งแต่วัยและหน้านี้อาจเป็นข้อสรุปของการค้นหาเป็นปี ๆ ! ฉันทดสอบข้อเสนอแนะที่คุณพูดถึงและนี่คือบันทึกของฉัน:

นี่คือสตริงทดสอบของฉัน:

นี่คือ "wròngwrìtten" string แต่ฉันไม่ได้รู้จักchàrsพิเศษของpù 'sòme' เพื่อดูthèm, convertèdโดยfùnctìon !! & แค่นั้นแหละ!

ฉันทำ INSERT เพื่อบันทึกสตริงนี้ในฐานข้อมูลในฟิลด์ที่ตั้งค่าเป็น utf8_general_ci

ชุดอักขระของหน้าของฉันคือ UTF-8

ถ้าฉันทำ INSERT แบบนั้นในฐานข้อมูลของฉันฉันมีตัวละครบางตัวที่อาจมาจากดาวอังคาร ...

ดังนั้นฉันต้องแปลงมันให้เป็น "sane" UTF-8 ฉันพยายามutf8_encode()แต่ตัวอักษรเอเลี่ยนยังคงบุกรุกฐานข้อมูลของฉัน ...

ดังนั้นฉันจึงพยายามใช้ฟังก์ชั่นที่forceUTF8โพสต์ในหมายเลข 8 แต่ในฐานข้อมูลสตริงที่บันทึกมีลักษณะดังนี้:

นี่คือ "wròngwrìtten" string bùtฉันnà toed เพื่อpù 's²²' chà rs พิเศษเพื่อดูthèm, convertèdโดยfùnctìon !! & แค่นั้นแหละ!

ดังนั้นการรวบรวมข้อมูลเพิ่มเติมในหน้านี้และรวมเข้ากับข้อมูลอื่น ๆ ในหน้าอื่น ๆ ฉันแก้ไขปัญหาของฉันด้วยวิธีนี้:

$finallyIDidIt = mb_convert_encoding(
  $string,
  mysql_client_encoding($resourceID),
  mb_detect_encoding($string)
);

ตอนนี้ในฐานข้อมูลของฉันฉันมีสตริงของฉันด้วยการเข้ารหัสที่ถูกต้อง

หมายเหตุ: หมายเหตุ เท่านั้นที่จะดูแลอยู่ในฟังก์ชั่นmysql_client_encoding! คุณต้องเชื่อมต่อกับฐานข้อมูลเพราะฟังก์ชั่นนี้ต้องการรหัสทรัพยากรเป็นพารามิเตอร์

แต่ก็ฉันเพิ่งเข้ารหัสอีกครั้งก่อนที่ INSERT ของฉันดังนั้นสำหรับฉันมันไม่ใช่ปัญหา


1
ทำไมคุณไม่ใช้การUTF-8เข้ารหัสไคลเอนต์สำหรับ mysql ตั้งแต่แรก? ไม่ต้องการการแปลงด้วยตนเองในลักษณะนี้
Esailija

2

มันง่าย: เมื่อคุณได้รับสิ่งที่ไม่ใช่ UTF-8 คุณต้องเข้ารหัสนั้นเป็น UTF-8

ดังนั้นเมื่อคุณกำลังเรียกฟีดบางอย่างที่เป็นมาตรฐาน ISO 8859-1 utf8_encodeแยกมันผ่าน

อย่างไรก็ตามหากคุณดึงข้อมูลฟีด UTF-8 คุณไม่จำเป็นต้องทำอะไรเลย


ขอบคุณ! ตกลงฉันสามารถค้นหาวิธีการเข้ารหัสฟีดโดยใช้การตรวจจับการเข้ารหัส mb () ใช่ไหม? แต่ฉันจะทำอะไรได้บ้างถ้าฟีดคือ ASCII utf8-encode () เป็นเพียง ISO-8859-1 ถึง UTF-8 ใช่ไหม
caw

ASCII เป็นชุดย่อยของ ISO-8859-1 และ UTF-8 ดังนั้นการใช้ utf8-encode () ไม่ควรทำการเปลี่ยนแปลง - ถ้าจริง ๆ แล้วมันแค่ ASCII
Michael Borgwardt

ดังนั้นฉันสามารถใช้ utf8_encode ได้ตลอดเวลาหากไม่ใช่ UTF-8 มันจะง่ายจริงๆ ข้อความที่เป็น ASCII ตามการเข้ารหัส mb-detect-encoding () มี "& # 228;" นี่เป็นอักขระ ASCII หรือไม่ หรือมันคือ HTML?
caw

นั่นคือ HTML ที่จริงแล้วมีการเข้ารหัสดังนั้นเมื่อคุณพิมพ์ในหน้าที่ระบุจะแสดงว่าตกลง หากคุณต้องการคุณสามารถ ut8_encode () ก่อนจากนั้น html_entity_decode ()
Seb

1
อักขระßถูกเข้ารหัสใน UTF-8 พร้อมกับลำดับไบต์ 0xC39F ตีความด้วย Windows-1252 ลำดับนั้นแทนอักขระสองตัวÂ (0xC3) และŸ (0x9F) และถ้าคุณเข้ารหัสลำดับไบต์นี้อีกครั้งด้วย UTF-8 คุณจะได้ 0xC383 0xC29F สิ่งที่แสดงถึงการใช้ใน Windows-1252 ดังนั้นความผิดพลาดของคุณคือจัดการข้อมูลที่เข้ารหัส UTF-8 นี้เป็นสิ่งที่มีการเข้ารหัสอื่นที่ไม่ใช่ UTF-8 ว่าลำดับไบต์นี้จะถูกนำเสนอเป็นตัวละครที่คุณเห็นเป็นเพียงเรื่องของการตีความ หากคุณใช้การเข้ารหัส / ชุดอักขระอื่น ๆ คุณอาจเห็นอักขระอื่น ๆ
Gumbo

1

php.net/mb_detect_encoding

echo mb_detect_encoding($str, "auto");

หรือ

echo mb_detect_encoding($str, "UTF-8, ASCII, ISO-8859-1");

ฉันไม่รู้ว่าผลลัพธ์คืออะไร แต่ฉันขอแนะนำให้คุณใช้ฟีดของคุณพร้อมการเข้ารหัสที่แตกต่างกันและลองใช้mb_detect_encodingงานได้หรือไม่

การอัปเดต
อัตโนมัติสั้นสำหรับ "ASCII, JIS, UTF-8, EUC-JP, SJIS" มันส่งกลับ charset ตรวจพบซึ่งคุณสามารถใช้การแปลงสตริงเพื่อ UTF-8 กับiconv

<?php
function convertToUTF8($str) {
    $enc = mb_detect_encoding($str);

    if ($enc && $enc != 'UTF-8') {
        return iconv($enc, 'UTF-8', $str);
    } else {
        return $str;
    }
}
?>

ฉันยังไม่ได้ทดสอบดังนั้นจึงไม่มีการรับประกัน และอาจจะมีวิธีที่ง่ายกว่า


ขอบคุณ. ข้อแตกต่างระหว่าง 'อัตโนมัติ' และ 'UTF-8, ASCII, ISO-8859-1' เป็นอาร์กิวเมนต์ที่สองคืออะไร คุณสมบัติ 'อัตโนมัติ' มีการเข้ารหัสเพิ่มเติมหรือไม่ ถ้าอย่างนั้นจะเป็นการดีกว่าถ้าใช้ 'อัตโนมัติ' ใช่ไหม หากใช้งานได้จริงโดยไม่มีข้อบกพร่องใด ๆ ฉันต้องเปลี่ยน "ASCII" หรือ "ISO-8859-1" เป็น "UTF-8" เท่านั้น อย่างไร?
caw

2
ฟังก์ชั่นของคุณใช้งานไม่ได้ในทุกกรณี บางครั้งฉันได้รับข้อผิดพลาด: ข้อสังเกตุ: iconv (): ตรวจพบอักขระที่ผิดกฎหมายในสตริงป้อนข้อมูลใน ...
caw

1

@harpax ที่เหมาะกับฉัน ในกรณีของฉันสิ่งนี้ดีพอ:

if (isUTF8($str)) { 
    echo $str; 
}
else
{
    echo iconv("ISO-8859-1", "UTF-8//TRANSLIT", $str);
}

0

หลังจากจัดเรียงสคริปต์ PHP ของคุณอย่าลืมบอกให้ mysql ทราบว่าคุณกำลังส่งชุดอักขระใดและต้องการรับรู้ซ้ำ

ตัวอย่าง: set character set utf8

การส่งข้อมูล utf8 ไปยังตาราง latin1 ในเซสชัน latin1 I / O จะให้ birdfeets ที่น่ารังเกียจเหล่านั้น ฉันเห็นสิ่งนี้ทุกวันในร้านค้า osCommerce กลับมาและที่สี่มันอาจดูขวา แต่ phpmyadmin จะแสดงความจริง โดยบอก mysql ว่าชุดอักขระที่คุณส่งผ่านนั้นจะจัดการกับการแปลงข้อมูล mysql ให้คุณ

วิธีการกู้คืนข้อมูล mysql ที่มีสัญญาณรบกวนนั้นเป็นอีกหนึ่งเธรดที่จะพูดคุย :)


0

รุ่นนี้ใช้สำหรับภาษาเยอรมัน แต่คุณสามารถแก้ไข $ CHARSETS และ $ TESTCHARS ได้

class CharsetDetector
{
private static $CHARSETS = array(
"ISO_8859-1",
"ISO_8859-15",
"CP850"
);
private static $TESTCHARS = array(
"€",
"ä",
"Ä",
"ö",
"Ö",
"ü",
"Ü",
"ß"
);
public static function convert($string)
{
    return self::__iconv($string, self::getCharset($string));
}
public static function getCharset($string)
{
    $normalized = self::__normalize($string);
    if(!strlen($normalized))return "UTF-8";
    $best = "UTF-8";
    $charcountbest = 0;
    foreach (self::$CHARSETS as $charset) {
        $str = self::__iconv($normalized, $charset);
        $charcount = 0;
        $stop   = mb_strlen( $str, "UTF-8");

        for( $idx = 0; $idx < $stop; $idx++)
        {
            $char = mb_substr( $str, $idx, 1, "UTF-8");
            foreach (self::$TESTCHARS as $testchar) {

                if($char == $testchar)
                {

                    $charcount++;
                    break;
                }
            }
        }
        if($charcount>$charcountbest)
        {
            $charcountbest=$charcount;
            $best=$charset;
        }
        //echo $text."<br />";
    }
    return $best;
}
private static function __normalize($str)
{

$len = strlen($str);
$ret = "";
for($i = 0; $i < $len; $i++){
    $c = ord($str[$i]);
    if ($c > 128) {
        if (($c > 247)) $ret .=$str[$i];
        elseif ($c > 239) $bytes = 4;
        elseif ($c > 223) $bytes = 3;
        elseif ($c > 191) $bytes = 2;
        else $ret .=$str[$i];
        if (($i + $bytes) > $len) $ret .=$str[$i];
        $ret2=$str[$i];
        while ($bytes > 1) {
            $i++;
            $b = ord($str[$i]);
            if ($b < 128 || $b > 191) {$ret .=$ret2; $ret2=""; $i+=$bytes-1;$bytes=1; break;}
            else $ret2.=$str[$i];
            $bytes--;
        }
    }
}
return $ret; 
}
private static function __iconv($string, $charset)
{
    return iconv ( $charset, "UTF-8" , $string );
}
}


0

รับการเข้ารหัสจากส่วนหัวและแปลงเป็น utf-8

$post_url='http://website.domain';

/// Get headers ////////////////////////////////////////////////////////////
function get_headers_curl($url) 
{ 
    $ch = curl_init(); 

    curl_setopt($ch, CURLOPT_URL,            $url); 
    curl_setopt($ch, CURLOPT_HEADER,         true); 
    curl_setopt($ch, CURLOPT_NOBODY,         true); 
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 
    curl_setopt($ch, CURLOPT_TIMEOUT,        15); 

    $r = curl_exec($ch); 
    return $r; 
}
$the_header = get_headers_curl($post_url);
/// check for redirect /////////////////////////////////////////////////
if (preg_match("/Location:/i", $the_header)) {
    $arr = explode('Location:', $the_header);
    $location = $arr[1];

    $location=explode(chr(10), $location);
    $location = $location[0];

$the_header = get_headers_curl(trim($location));
}
/// Get charset /////////////////////////////////////////////////////////////////////
if (preg_match("/charset=/i", $the_header)) {
    $arr = explode('charset=', $the_header);
    $charset = $arr[1];

    $charset=explode(chr(10), $charset);
    $charset = $charset[0];
    }
///////////////////////////////////////////////////////////////////////////////
// echo $charset;

if($charset && $charset!='UTF-8') { $html = iconv($charset, "UTF-8", $html); }

0

Ÿßเป็นอาการภาษาต่างดาวสำหรับ ในฐานข้อมูลของคุณคุณอาจมีเลขฐานสิบหก

DF if the column is "latin1",
C39F if the column is utf8 -- OR -- it is latin1, but "double-encoded"
C383C5B8 if double-encoded into a utf8 column

คุณไม่ควรใช้ฟังก์ชั่นการเข้ารหัส / ถอดรหัสใน PHP; คุณควรตั้งค่าฐานข้อมูลและการเชื่อมต่ออย่างถูกต้องแทน

หาก MySQL มีส่วนเกี่ยวข้องให้ดูที่: ปัญหาเกี่ยวกับตัวอักษร utf8; สิ่งที่ฉันเห็นไม่ใช่สิ่งที่ฉันเก็บไว้


0

ฉันหาวิธีแก้ปัญหาได้ที่นี่http://deer.org.ua/2009/10/06/1/

class Encoding
{
    /**
     * http://deer.org.ua/2009/10/06/1/
     * @param $string
     * @return null
     */
    public static function detect_encoding($string)
    {
        static $list = ['utf-8', 'windows-1251'];

        foreach ($list as $item) {
            try {
                $sample = iconv($item, $item, $string);
            } catch (\Exception $e) {
                continue;
            }
            if (md5($sample) == md5($string)) {
                return $item;
            }
        }
        return null;
    }
}

$content = file_get_contents($file['tmp_name']);
$encoding = Encoding::detect_encoding($content);
if ($encoding != 'utf-8') {
    $result = iconv($encoding, 'utf-8', $content);
} else {
    $result = $content;
}

ฉันคิดว่า@เป็นการตัดสินใจที่ไม่ดีและทำการเปลี่ยนแปลงบางอย่างเพื่อแก้ปัญหาจาก deer.org.ua


0

คำตอบที่โหวตมากที่สุดไม่ทำงาน นี่คือของฉันและหวังว่ามันจะช่วยได้

function toUTF8($raw) {
    try{
        return mb_convert_encoding($raw, "UTF-8", "auto"); 
    }catch(\Exception $e){
        return mb_convert_encoding($raw, "UTF-8", "GBK"); 
    }
}

1
คุณมีเหตุผลใดบ้างหรือไฟล์ของคุณแตกต่างกันอย่างไร ส่วนไหนที่ไม่ได้ผลสำหรับคุณ ตัวอย่างเช่น: อักขระภาษาเยอรมันตัวพิมพ์ใหญ่ไม่ได้แปลงอย่างถูกต้อง อยากรู้ว่า "GBK" คืออะไร?
SherylHohman

-1

เมื่อคุณพยายามจัดการหลายภาษาเช่นญี่ปุ่นและเกาหลีคุณอาจมีปัญหา mb_convert_encoding พร้อมพารามิเตอร์ 'อัตโนมัติ' ทำงานได้ไม่ดี การตั้งค่า mb_detect_order ('ASCII, UTF-8, JIS, EUC-JP, SJIS, EUC-KR, UHC') ไม่ได้ช่วยเพราะมันจะตรวจจับ EUC- * ผิด

ฉันได้ข้อสรุปว่าตราบใดที่สตริงอินพุตมาจาก HTML ก็ควรใช้ 'charset' ในองค์ประกอบเมตา ฉันใช้Simple HTML DOM Parserเพราะรองรับ HTML ที่ไม่ถูกต้อง

ตัวอย่างด้านล่างแยกองค์ประกอบชื่อจากหน้าเว็บ หากคุณต้องการแปลงทั้งหน้าคุณอาจต้องการลบบางบรรทัด

<?php
require_once 'simple_html_dom.php';

echo convert_title_to_utf8(file_get_contents($argv[1])), PHP_EOL;

function convert_title_to_utf8($contents)
{
    $dom = str_get_html($contents);
    $title = $dom->find('title', 0);
    if (empty($title)) {
        return null;
    }
    $title = $title->plaintext;
    $metas = $dom->find('meta');
    $charset = 'auto';
    foreach ($metas as $meta) {
        if (!empty($meta->charset)) { // html5
            $charset = $meta->charset;
        } else if (preg_match('@charset=(.+)@', $meta->content, $match)) {
            $charset = $match[1];
        }
    }
    if (!in_array(strtolower($charset), array_map('strtolower', mb_list_encodings()))) {
        $charset = 'auto';
    }
    return mb_convert_encoding($title, 'UTF-8', $charset);
}

-1

ฉันมีปัญหาเดียวกันกับphpQuery ( ISO-8859-1แทนที่จะเป็นUTF-8 ) และการแฮ็คนี้ช่วยฉัน:

$html = '<?xml version="1.0" encoding="UTF-8" ?>' . $html;

mb_internal_encoding('UTF-8'), phpQuery::newDocumentHTML($html, 'utf-8'), mbstring.internal_encodingและกิจวัตรอื่น ๆ ที่ไม่ได้มีผลใด ๆ


-1

ลองโดยไม่ต้อง 'อัตโนมัติ'

นั่นคือ:

mb_detect_encoding($text)

แทน:

mb_detect_encoding($text, 'auto')

ข้อมูลเพิ่มเติมสามารถดูได้ที่นี่: mb_detect_encoding

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.