Wykryj kodowanie i zrób wszystko UTF-8

Czytam wiele tekstów z różnych kanałów RSS i wstawiam je do mojej bazy danych.

Oczywiście istnieje kilka różnych kodowań znaków używanych w kanałach, np. UTF-8 i ISO-8859-1.

Niestety, czasami występują problemy z kodowaniem tekstów. Przykład:

  1. "ß" w "Fußball" powinno wyglądać tak w mojej bazie danych: "Ÿ". Jeśli jest to "Ÿ", jest wyświetlany poprawnie.

  2. Czasami " ß " w " Fußball" wygląda tak w mojej bazie danych: "ß". Wtedy jest wyświetlany nieprawidłowo, oczywiście.

  3. W innych przypadkach " ß " zapisuje się jako "ß" - więc bez zmian. Wtedy jest również wyświetlany błędnie.

Co mogę zrobić, aby uniknąć przypadków 2 i 3?

Jak mogę zrobić wszystko z tego samego kodowania, najlepiej UTF-8? Kiedy muszę użyć utf8_encode(), kiedy muszę użyć utf8_decode() (jest jasne, jaki jest efekt, ale kiedy muszę użyć funkcji?) i kiedy muszę nic nie robić z wejście?

Możesz mi pomóc i powiedzieć, jak zrobić to samo kodowanie? Może z funkcją mb_detect_encoding()? Czy mogę napisać do tego funkcję? Więc moje problemy to:
  1. Jak sprawdzić, jakiego kodowania używa tekst?
  2. Jak przekonwertować go na UTF-8-cokolwiek to jest stare kodowanie?

Czy taka funkcja zadziała?

function correct_encoding($text) {
    $current_encoding = mb_detect_encoding($text, 'auto');
    $text = iconv($current_encoding, 'UTF-8', $text);
    return $text;
}
Testowałem go, ale nie działa. Co z nim nie tak?
Author: JakeGould, 2009-05-26

24 answers

Jeśli zastosujesz utf8_encode() do już napisu UTF8, zwróci zniekształcone wyjście UTF8.

Zrobiłem funkcję, która rozwiązuje wszystkie te problemy. Nazywa się Encoding::toUTF8().

Nie musisz wiedzieć, jakie jest kodowanie Twoich ciągów. Może to być Latin1 (iso 8859-1), Windows-1252 lub UTF8, lub łańcuch może mieć ich mieszankę. Encoding::toUTF8() skonwertuje wszystko do UTF8.

Zrobiłem to, ponieważ usługa dawała mi kanał danych wszystkie popaprane, mieszając UTF8 i Latin1 w tym samym sznurek.

Użycie:

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);

Pobierz:

Https://github.com/neitanod/forceutf8

Aktualizacja:

Dodałem jeszcze jedną funkcję, Encoding::fixUFT8(), która naprawi każdy łańcuch UTF8, który wygląda na zniekształcony.

Użycie:

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

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

Przykłady:

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");

Wyświetli:

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

Update: przekształciłem funkcję (forceUTF8) w rodzinę funkcji statycznych na klasie o nazwie Encoding. Nowa funkcja to Encoding::toUTF8().

 321
Author: Sebastián Grignoli,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-01 14:39:33

Najpierw musisz wykryć, jakie kodowanie zostało użyte. Podczas parsowania kanałów RSS (prawdopodobnie przez HTTP), powinieneś przeczytać kodowanie z parametru charset z Content-Type pole nagłówka HTTP . Jeśli kodowanie nie istnieje, odczytaj kodowanie z atrybutu encoding instrukcji przetwarzania XML. Jeśli tego też brakuje, użyj UTF - 8 zgodnie ze specyfikacją .


Edit Oto co prawdopodobnie zrobiłbym:

Użyłbym cURL Aby wysłać i pobrać odpowiedź. Pozwala to ustawić określone pola nagłówka i pobrać nagłówek odpowiedzi. Po pobraniu odpowiedzi musisz przeanalizować odpowiedź HTTP i podzielić ją na nagłówek i treść. Nagłówek powinien zawierać pole nagłówka Content-Type zawierające typ MIME oraz (miejmy nadzieję) parametr charset z kodowaniem / kodowaniem. Jeśli nie, przeanalizujemy XML PI pod kątem obecności atrybutu encoding i uzyskamy kodowanie stamtąd. Jeśli to brakuje również specyfikacji XML definiującej użycie UTF-8 jako kodowania.

$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();
    }
}
 72
Author: Gumbo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-27 19:29:23

Wykrywanie kodowania jest trudne.

mb_detect_encoding działa poprzez zgadywanie, na podstawie liczby kandydatów, że go zdasz. W niektórych kodowaniach pewne sekwencje bajtowe są nieprawidłowe, a zatem można rozróżnić różne kandydatury. Niestety, istnieje wiele kodowań, w których te same bajty są ważne (ale inne). W takich przypadkach nie ma sposobu na określenie kodowania; możesz zaimplementować własną logikę, aby zgadywać w tych przypadkach. Na przykład dane pochodzące z Strona japońska może mieć bardziej prawdopodobne Japońskie kodowanie.

Dopóki zajmujesz się tylko językami zachodnioeuropejskimi, trzy główne kodowania do rozważenia to utf-8, iso-8859-1 i cp-1252. Ponieważ są to domyślne wartości dla wielu platform, są one również najczęściej błędnie zgłaszane. Np. jeśli ludzie używają różnych kodowań, prawdopodobnie będą szczerzy, ponieważ w przeciwnym razie ich oprogramowanie pękłoby bardzo często. Dlatego dobrą strategią jest zaufanie dostawcy, chyba że kodowanie jest zgłaszane jako jedno z tych trzech. Należy jeszcze sprawdzić, czy rzeczywiście jest poprawny, używając mb_check_encoding (zauważ, że valid nie jest tym samym, co jako - to samo wejście może być ważne dla wielu kodowań). Jeśli jest to jeden z nich, możesz użyć mb_detect_encoding, aby je rozróżnić. Na szczęście jest to dość deterministyczne; wystarczy użyć odpowiedniej sekwencji detekcji, którą jest UTF-8,ISO-8859-1,WINDOWS-1252.

Po wykryciu kodowania musisz przekonwertować go na swój wewnętrzny reprezentacja ({[7] } jest jedynym rozsądnym wyborem). Funkcja utf8_encode przekształca ISO-8859-1 na UTF-8, więc może być używana tylko dla danego typu wejściowego. W przypadku innych kodowań należy użyć mb_convert_encoding.

 35
Author: troelskn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-04 16:04:46

Ten arkusz zawiera listę typowych błędów związanych z obsługą UTF-8 w PHP: http://developer.loftdigital.com/blog/php-utf-8-cheatsheet

Ta funkcja wykrywająca wielobajtowe znaki w łańcuchu może również okazać się pomocna (źródło):


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);
}
 11
Author: miek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-09 15:05:52

A naprawdę ładny sposób implementacji isUTF8-funkcji można znaleźć na php.net :

function isUTF8($string) {
    return (utf8_encode(utf8_decode($string)) == $string);
}
 11
Author: harpax,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-30 03:16:20

Mała uwaga, powiedziałeś, że " ß "powinno być wyświetlane jako" Ÿ " w bazie danych.

To prawdopodobnie dlatego, że używasz bazy danych z kodowaniem znaków latin1 lub prawdopodobnie twoje połączenie php-mysql jest ustawione źle, to jest, php wierzy, że Twój mysql jest ustawiony na utf-8, więc wysyła dane jako utf8, ale twój mysql wierzy, że php wysyła dane zakodowane jako iso-8859-1, więc może po raz kolejny spróbować zakodować wysłane dane jako utf-8, powodując tego rodzaju problemy.

Spójrz na to może Ci pomóc: http://php.net/manual/en/function.mysql-set-charset.php

 9
Author: Krynble,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-30 03:16:05

Twoje kodowanie wygląda tak, jakbyś kodował w UTF-8dwa razy ; to znaczy, z innego kodowania, do UTF-8 i ponownie do UTF-8. Tak jakbyś miał iso-8859-1, konwertował z iso-8859-1 na utf-8 i traktował nowy ciąg jako iso-8859-1 dla kolejnej konwersji na UTF-8.

Oto jakiś pseudokod tego co zrobiłeś:

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

Powinieneś spróbować:

  1. detect encoding using mb_detect_encoding() or whatever you like to use
  2. jeśli jest to UTF-8, Konwertuj na iso-8859-1 i powtórz Krok 1
  3. na koniec Konwertuj z powrotem do UTF-8

Zakładając, że w" środku " konwersji użyłeś iso-8859-1. Jeśli używałeś windows-1252, przekonwertuj na windows-1252 (latin1). Oryginalne kodowanie źródłowe nie jest ważne; to, którego użyłeś w wadliwej, drugiej konwersji jest.

To moje przypuszczenie, co się stało; niewiele można było zrobić, aby uzyskać cztery bajty zamiast jednego rozszerzonego bajtu ASCII.

Język niemiecki również używa iso-8859-2 i windows-1250 (latin2).

 3
Author: Ivan Vučica,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-04 10:07:44

Musisz przetestować charset na wejściu, ponieważ odpowiedzi mogą być kodowane różnymi kodowaniami.
wymuszam wysłanie całej zawartości do UTF-8, wykonując detekcję i tłumaczenie za pomocą następującej funkcji:

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;
      }
    }
  }
}

Ta procedura zmieni wszystkie zmienne PHP Pochodzące ze zdalnego hosta w UTF-8.
lub zignorować wartość, jeśli kodowanie nie może być wykryte lub przekonwertowane. Możesz dostosować go do swoich potrzeb.
po prostu wywołaj go przed użyciem zmiennych.

 3
Author: cavila,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-16 16:46:49

Ciekawostką w mb_detect_encoding i mb_convert_encoding jest to, że kolejność sugerowanych kodowań ma znaczenie:

// $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)

Więc możesz chcieć użyć określonej kolejności przy określaniu oczekiwanych kodowań. Pamiętaj jednak, że nie jest to niezawodne.

 3
Author: Halil Özgür,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-11 17:58:32

To proste: kiedy dostajesz coś, co nie jest UTF8, musisz to zakodować w utf8.

Więc, gdy pobierasz określony kanał, który jest ISO-8859-1, parsuj go przez utf8_encode.

Jednakże, jeśli pobierasz kanał UTF8, nie musisz nic robić.

 2
Author: Seb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-26 13:55:14

Opracowanie kodowania znaków kanałów RSS wydaje się być skomplikowane . Nawet normalne strony internetowe często pomijają lub kłamią o ich kodowaniu.

Więc możesz spróbować użyć poprawnego sposobu, aby wykryć kodowanie, A następnie powrócić do jakiejś formy automatycznego wykrywania (zgadywania).

 2
Author: Kevin ORourke,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-26 14:02:41

Wiem, że to starsze pytanie, ale myślę, że użyteczna odpowiedź nigdy nie zaszkodzi. Miałem problemy z moim kodowaniem między aplikacją desktopową, SQLite i zmiennymi GET / POST. Niektóre byłyby w UTF-8, inne w ASCII, i w zasadzie wszystko by się spieprzyło, gdy w grę wchodziły obce znaki.

Oto moje rozwiązanie. To scrubs GET / POST / REQUEST (pominąłem pliki cookie, ale można je dodać w razie potrzeby) na każdym załadowaniu strony przed przetwarzaniem. Działa dobrze w nagłówku. PHP wyświetla ostrzeżenia, jeśli nie może wykryć kodowania źródłowego automatycznie, więc te ostrzeżenia są tłumione przez @ ' S.
//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){}
 2
Author: jocull,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-23 05:52:59

Sprawdzałem rozwiązania do kodowania od wieków, a ta strona to chyba podsumowanie lat poszukiwań! Przetestowałem niektóre z sugestii, o których wspomniałeś, a oto moje notatki:

To jest mój ciąg testowy:

To jest "wròng wrìtten" string bùt i nèed to pù 'sòme' special chàrs to see thèm, convertèd by fùnctìon!! i to jest to!

Wykonuję INSERT, aby zapisać ten ciąg na DB w polu, które jest ustawione jako utf8_general_ci

Charset mojej strony jest UTF-8

Jeśli zrobię taką wstawkę, w moim DB mam kilka znaków prawdopodobnie pochodzących z Marsa... więc muszę je przekonwertować na jakieś "zdrowe" UTF-8. Próbowałem utf8_encode(), ale i tak znaki kosmitów atakowały moją bazę danych...

Więc próbowałem użyć funkcji forceUTF8 napisanej na cyfrze 8 ale na DB zapisany ciąg wygląda tak:

To jest "wrÃ2ng wrÃtten" string bÃ1t i nÃed to pã1' sã2me ' special chà rs to see thÃm, convertÃd by fÃ1nctÃon!! & to to!

Więc zbierając więcej informacji na tej stronie i łącząc je z innymi informacjami na innych stronach rozwiązałem mój problem z tym rozwiązaniem:

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

Teraz w mojej bazie mam swój ciąg znaków z poprawnym kodowaniem.

Uwaga: Jedyną uwagą, którą należy się zająć, jest funkcja mysql_client_encoding! Musisz być podłączony do DB, ponieważ ta funkcja chce ID zasobu jako parametr.

Ale cóż, po prostu robię to ponowne kodowanie przed moją wstawką, więc dla mnie nie jest to problem.

Mam nadzieję, że to pomoże komuś takiemu jak ta strona pomogła mi!

Dzięki wszystkim!

Mauro

 2
Author: Mauro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-29 11:06:24

Php.net/mb_detect_encoding

echo mb_detect_encoding($str, "auto");

Lub

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

Naprawdę Nie wiem, jakie są wyniki, ale sugerowałbym, abyś wziął kilka kanałów z różnymi kodowaniami i spróbował, czy mb_detect_encoding działa, czy nie.

Update
auto to skrót od "ASCII, JIS, UTF-8, EUC-JP, SJIS". zwraca wykryty zestaw znaków, za pomocą którego można przekonwertować łańcuch znaków na utf-8 za pomocą iconv .

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

    if ($enc && $enc != 'UTF-8') {
        return iconv($enc, 'UTF-8', $str);
    } else {
        return $str;
    }
}
?>
Nie testowałem go, więc nie mam gwarancji. a może jest coś prostszego sposób.
 1
Author: stefs,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-26 15:18:05

@Harpax to mi pomogło. W moim przypadku to wystarczy:

if (isUTF8($str)) { 
    echo $str; 
}
else
{
    echo iconv("ISO-8859-1", "UTF-8//TRANSLIT", $str);
}
 1
Author: PJ Brunet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-07-27 00:48:03

Po uporządkowaniu skryptów php, nie zapomnij powiedzieć mysql jaki charset przekazujesz i chcesz je odtworzyć.

Przykład: set character set utf8

Przekazywanie danych utf8 do tabeli latin1 w sesji wejścia/Wyjścia latin1 daje te nieprzyjemne odczucia dla ptaków. Widzę to co drugi dzień w sklepach oscommerce. Powrót i czwarty może wydawać się słuszny. Ale phpmyadmin pokaże prawdę. Mówiąc mysql jaki charset przekazujesz, obsłuży konwersję danych mysql dla ty.

Jak odzyskać istniejące zakodowane dane mysql to kolejny wątek do omówienia. :)

 0
Author: tim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-18 19:40:18

Ta wersja jest dla języka niemieckiego, ale można modyfikować $ CHARSETS i $ 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
Author: Lukas Gottschall,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-22 18:53:49

Pobierz kodowanie z nagłówków i przekonwertuj je na 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
Author: Arsen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-01 09:20:41

Ÿ jest Mojibake dla ß. W swojej bazie danych możesz mieć hex

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

Powinieneś nie używać żadnych funkcji kodowania/dekodowania w PHP; zamiast tego powinieneś poprawnie skonfigurować bazę danych i połączenie z nią.

Jeśli chodzi o MySQL, Zobacz: problemy ze znakami utf8; to, co widzę, nie jest tym, co zapisałem

 0
Author: Rick James,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:41

I find solution here 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;
}

Myślę, że @ jest zła decyzja, i dokonać pewnych zmian w rozwiązaniu z deer.org.ua;

 0
Author: Paul,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-13 15:05:09

Najczęściej głosowana odpowiedź nie działa. Mam nadzieję, że to pomoże.

function toUTF8($raw) {
    try{
        return mb_convert_encoding($raw, "UTF-8", "auto"); 
    }catch(\Exception $e){
        return mb_convert_encoding($raw, "UTF-8", "GBK"); 
    }
}
 0
Author: fzyzcjy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-29 03:51:00

Kiedy próbujesz obsługiwać wiele języków, takich jak japoński i koreański, możesz mieć kłopoty. mb_convert_encoding z parametrem 'auto' nie działa dobrze. Ustawienie mb_detect_order ('ASCII,UTF-8,JIS,EUC-JP,SJIS,EUC-KR,UHC') nie pomaga, ponieważ błędnie wykryje EUC -*.

Doszedłem do wniosku, że tak długo, jak ciągi wejściowe pochodzą z HTML, powinien on używać 'charset' w elemencie meta. Używam prostego HTML parsera dom ponieważ obsługuje nieprawidłowy HTML.

Poniżej fragmenty element tytułu ze strony internetowej. Jeśli chcesz przekonwertować całą stronę, możesz usunąć niektóre linie.

<?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
Author: Nobu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-14 23:29:02

Miałem ten sam problem z phpQuery (ISO-8859-1 zamiast UTF-8) i ten hack mi pomógł:

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

mb_internal_encoding('UTF-8'), phpQuery::newDocumentHTML($html, 'utf-8'), mbstring.internal_encoding a inne manipulacje nie przyniosły żadnego efektu.

 -1
Author: user2448995,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-15 20:35:51

Spróbuj bez 'auto'

Czyli:

mb_detect_encoding($text)

Zamiast:

mb_detect_encoding($text, 'auto')

Więcej informacji można znaleźć tutaj: mb_detect_encoding

 -1
Author: tkartas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-22 21:03:40