Detecta la codificación y haz que todo sea UTF-8


Estoy leyendo muchos textos de varios canales RSS e insertándolos en mi base de datos.

Por supuesto, hay varias codificaciones de caracteres diferentes utilizadas en los feeds, por ejemplo, UTF-8 e ISO-8859-1.

Desafortunadamente, a veces hay problemas con la codificación de los textos. Ejemplo:

  1. El " ß " en "Fußball" debería verse así en mi base de datos: "Ÿ". Si es un "Ÿ", se muestra correctamente.

  2. A veces, la " ß " en " Fußball" se ve así en mi base de datos: "ƒ". Entonces se muestra erróneamente, por supuesto.

  3. En otros casos, el " ß "se guarda como un" ß " - so sin ningún cambio. Entonces también se muestra incorrectamente.

¿Qué puedo hacer para evitar los casos 2 y 3?

¿Cómo puedo hacer que todo tenga la misma codificación, preferiblemente UTF-8? ¿Cuándo debo usar utf8_encode(), cuándo debo usar utf8_decode() (está claro cuál es el efecto, pero cuándo debo usar las funciones?) y cuando debo hacer nada con el la entrada?

¿Puedes ayudarme y decirme cómo hacer que todo tenga la misma codificación? Tal vez con la función mb_detect_encoding()? Puedo escribir una función para esto? Así que mis problemas son:

  1. ¿Cómo averiguar qué codificación utiliza el texto?
  2. ¿Cómo convertirlo a UTF-8-sea cual sea la codificación antigua?

¿Funcionaría una función como esta?

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

Lo he probado pero no funciona. ¿Qué tiene de malo?

Author: JakeGould, 2009-05-26

24 answers

Si aplica utf8_encode() a una cadena ya UTF8, devolverá una salida UTF8 confusa.

Hice una función que aborda todos estos problemas. Se llama Encoding::toUTF8().

No necesita saber cuál es la codificación de sus cadenas. Puede ser Latin1 (iso 8859-1), Windows-1252 o UTF8, o la cadena puede tener una mezcla de ellos. Encoding::toUTF8() convertirá todo a UTF8.

Lo hice porque un servicio me estaba dando un feed de datos todos desordenados, mezclando UTF8 y Latin1 en el mismo cadena.

Uso:

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

Descargar:

Https://github.com/neitanod/forceutf8

Actualización:

He incluido otra función, Encoding::fixUFT8(), que arreglará cada cadena UTF8 que parezca confusa.

Uso:

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

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

Ejemplos:

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

Producirá:

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

Actualizar: He transformado la función (forceUTF8) en una familia de funciones estáticas en una clase llamada Encoding. La nueva función es 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-01 14:39:33

Primero debe detectar qué codificación se ha utilizado. Como usted está analizando los canales RSS (probablemente a través de HTTP), usted debe leer la codificación del parámetro charset de la Content-Type HTTP header field . Si no está presente, lea la codificación desde el atributo encoding de la instrucción de procesamiento XML . Si eso también falta, use UTF-8 como se define en la especificación.


Edit Esto es lo que probablemente haría:

Usaría cURL para enviar y obtener la respuesta. Eso le permite establecer campos de encabezado específicos y obtener el encabezado de respuesta también. Después de obtener la respuesta, debe analizar la respuesta HTTP y dividirla en encabezado y cuerpo. El encabezado debe contener el campo de encabezado Content-Type que contiene el tipo MIME y (con suerte) el parámetro charset con la codificación/charset también. Si no, analizaremos el XML PI para la presencia del atributo encoding y obtendremos la codificación desde allí. Si eso es también faltan, las especificaciones XML definen usar UTF-8 como codificación.

$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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-27 19:29:23

Detectar la codificación es difícil.

mb_detect_encoding funciona adivinando, basado en un número de candidatos que lo apruebas. En algunas codificaciones, ciertas secuencias de bytes no son válidas, por lo que puede distinguir entre varios candidatos. Desafortunadamente, hay muchas codificaciones, donde los mismos bytes son válidos (pero diferentes). En estos casos, no hay forma de determinar la codificación; puede implementar su propia lógica para hacer conjeturas en estos casos. Por ejemplo, los datos procedentes de un Sitio japonés podría ser más probable que tenga una codificación japonesa.

Mientras solo trates con idiomas de Europa Occidental, las tres codificaciones principales a considerar son utf-8, iso-8859-1 y cp-1252. Dado que estos son valores predeterminados para muchas plataformas, también son los más propensos a ser reportados erróneamente. Eg. si la gente usa diferentes codificaciones, es probable que sean francos al respecto, ya que de lo contrario su software se rompería muy a menudo. Por lo tanto, una buena estrategia es confiar en el proveedor, a menos que el la codificación se reporta como una de esas tres. Usted todavía debe comprobar de nuevo que sí es válida, usando mb_check_encoding (tenga en cuenta que válido no es lo mismo que siendo - la misma entrada puede ser válido para muchos codificaciones). Si es uno de ellos, puede usar mb_detect_encoding para distinguir entre ellos. Afortunadamente eso es bastante determinista; Solo necesita usar la secuencia de detección adecuada, que es UTF-8,ISO-8859-1,WINDOWS-1252.

Una vez que haya detectado la codificación que necesita para convertir a su interno la representación (UTF-8 es la única opción sana). La función utf8_encode transforma ISO-8859-1 a UTF-8, por lo que solo se puede usar para ese tipo de entrada en particular. Para otras codificaciones, utilice 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-07-04 16:04:46

Esta hoja de trucos enumera algunas advertencias comunes relacionadas con el manejo de UTF-8 en PHP: http://developer.loftdigital.com/blog/php-utf-8-cheatsheet

Esta función detectando caracteres multibyte en una cadena también podría resultar útil (source):


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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-06-09 15:05:52

Una realmente buena manera de implementar una isUTF8-función se puede encontrar en 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-11-30 03:16:20

Un pequeño aviso, dijiste que el "ß" debería mostrarse como "Ÿ "en tu base de datos.

Esto es probablemente porque está utilizando una base de datos con codificación de caracteres latin1 o posiblemente su conexión php-mysql está mal establecida, esto es, php cree que su mysql está configurado para usar utf-8, por lo que envía datos como utf8, pero su mysql cree que php está enviando datos codificados como iso-8859-1, por lo que una vez más puede intentar codificar sus datos enviados como utf-8, causando este tipo de problemas.

Echa un vistazo a esto, puede ayudarle: 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-11-30 03:16:05

Su codificación parece que codificó en UTF-8 dos veces; es decir, de alguna otra codificación, en UTF-8, y nuevamente en UTF-8. Como si tuviera iso-8859-1, convertido de iso-8859-1 a utf-8, y trató la nueva cadena como iso-8859-1 para otra conversión a UTF-8.

Aquí hay un pseudocódigo de lo que hiciste:

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

Deberías probar:

  1. detecta la codificación usando mb_detect_encoding() o lo que quieras usar
  2. si es UTF-8, convertir a iso-8859-1, y repita el paso 1
  3. finalmente, vuelva a convertir en UTF-8

Eso supone que en la conversión "media" usaste iso-8859-1. Si usó windows-1252, conviértalo en windows-1252 (latin1). La codificación de origen original no es importante; la que utilizó en la segunda conversión defectuosa lo es.

Esta es mi conjetura de lo que sucedió; hay muy poco más que podría haber hecho para obtener cuatro bytes en lugar de un byte ASCII extendido.

El idioma alemán también utiliza iso-8859-2 y 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-06-04 10:07:44

Necesita probar el conjunto de caracteres en la entrada ya que las respuestas pueden venir codificadas con diferentes codificaciones.
Fuerzo todo el contenido enviado a UTF-8 haciendo detección y traducción usando la siguiente función:

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

Esa rutina convertirá todas las variables PHP que vienen del host remoto en UTF-8.
O ignore el valor si la codificación no se pudo detectar o convertir.
Puede personalizarlo según sus necesidades.
Simplemente invócalo antes de usar las variables.

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-12-16 16:46:49

Lo interesante de mb_detect_encoding y mb_convert_encoding es que el orden de las codificaciones que sugieres sí importa:

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

Por lo tanto, es posible que desee usar un orden específico al especificar las codificaciones esperadas. Sin embargo, tenga en cuenta que esto no es infalible.

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-11 17:58:32

Es simple: cuando obtienes algo que no es UTF8, debes CODIFICARLO EN utf8.

Por lo tanto, cuando usted está buscando un determinado feed que es ISO-8859-1 analizar a través de utf8_encode.

Sin embargo, si estás buscando un feed UTF8, no necesitas hacer nada.

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-26 13:55:14

Elaborar la codificación de caracteres de los canales RSS parece ser complicado. Incluso las páginas web normales a menudo omiten, o mienten sobre, su codificación.

Así que podría intentar usar la forma correcta de detectar la codificación y luego recurrir a alguna forma de detección automática (adivinar).

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-26 14:02:41

Sé que esta es una pregunta antigua, pero me imagino que una respuesta útil nunca está de más. Estaba teniendo problemas con mi codificación entre una aplicación de escritorio, SQLite y las variables GET/POST. Algunos estarían en UTF-8, otros estarían en ASCII, y básicamente todo se arruinaría cuando se involucraran personajes extranjeros.

Aquí está mi solución. Borra su GET / POST / REQUEST (Omití las cookies, pero podría agregarlas si lo desea) en cada carga de página antes de procesarlas. Funciona bien en un encabezado. PHP lanzará advertencias si no puede detectar la codificación de origen automáticamente, por lo que estas advertencias se suprimen con @'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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-05-23 05:52:59

Estaba buscando soluciones para la codificación desde hace SIGLOS, y esta página es probablemente la conclusión de años de búsqueda! Probé algunas de las sugerencias que mencionaste y aquí están mis notas:

Esta es mi cadena de prueba:

Esta es una cadena" wròng wrìtten " bùt I nèed to pù 'sòme' especial chàrs to see thèm, convertèd by fùnctìon!! & ¡eso es!

Hago un INSERT para guardar esta cadena en una BD en un campo que se establece como utf8_general_ci

El conjunto de caracteres de mi página es UTF-8

Si hago una INSERCIÓN así, en mi DB tengo algunos caracteres probablemente procedentes de Marte... así que necesito convertirlos en un UTF-8" cuerdo". Lo intenté utf8_encode() pero aún así los alienígenas estaban invadiendo mi base de datos...

Así que intenté usar la función forceUTF8 publicada en el número 8 pero en DB la cadena guardada se ve así:

Este es un" wrÃ2ng wrÃtten " string bÃ1t I nÃed to pÃ1 'sÃ2me' special Chà rs para ver thÃm, convertÃd por fÃ1nctÃon!! & eso es it!

Así que recopilando algunas informaciones más en esta página y fusionándolas con otras informaciones en otras páginas, resolví mi problema con esta solución:

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

Ahora en mi base de datos tengo mi cadena con la codificación correcta.

NOTA: La única nota a tener en cuenta es en función mysql_client_encoding! Necesita estar conectado a la base de datos porque esta función quiere un ID de recurso como parámetro.

Pero bueno, yo solo hago que re-codificación antes de mi INSERCIÓN por lo que para mí no es un problema.

Espero que esto ayude a alguien como esta página me ayudó!

Gracias a todos!

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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-04-29 11:06:24

Php.net/mb_detect_encoding

echo mb_detect_encoding($str, "auto");

O

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

Realmente no sé cuáles son los resultados, pero sugeriría que solo tome algunos de sus feeds con diferentes codificaciones y pruebe si mb_detect_encoding funciona o no.

Update
auto es la abreviatura de"ASCII,JIS,UTF-8,EUC-JP,SJIS". devuelve el conjunto de caracteres detectado, que puede usar para convertir la cadena a utf-8 con iconv.

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

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

No lo he probado, así que no hay garantía. y tal vez hay una más simple manera.

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-26 15:18:05

@harpax que funcionó para mí. En mi caso, esto es lo suficientemente bueno:

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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-07-27 00:48:03

Después de ordenar sus scripts php, no olvide decirle a mysql qué conjunto de caracteres está pasando y le gustaría recibir.

Ejemplo: set character set utf8

Pasar datos utf8 a una tabla latin1 en una sesión de E/S latin1 da esos desagradables birdfeet. Veo esto cada dos días en las tiendas oscommerce. Atrás y cuarto puede parecer correcto. Pero phpmyadmin mostrará la verdad. Al decirle a mysql qué conjunto de caracteres está pasando, manejará la conversión de datos mysql para usted.

Cómo recuperar datos mysql codificados existentes es otro tema para discutir. :)

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-18 19:40:18

Esta versión es para el idioma alemán, pero puede modificar los CHAR CHARSETS y los TEST 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-22 18:53:49

Obtenga la codificación de las cabeceras y conviértala a 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-01 09:20:41

Ÿ es Mojibake para ß. En su base de datos, puede tener 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

Debe no usar ninguna función de codificación/decodificación en PHP; en su lugar, debe configurar la base de datos y la conexión a ella correctamente.

Si MySQL está involucrado, vea: Problemas con caracteres utf8; lo que veo no es lo que almacené

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:10:41

Aquí encuentro la solución 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;
}

Creo que @ es una mala decisión, y hacer algunos cambios a la solución de 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-13 15:05:09

La respuesta más votada no funciona. Aquí está el mío y espero que ayude.

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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-29 03:51:00

Cuando intenta manejar múltiples idiomas como el Japonés y el coreano podría meterse en problemas. mb_convert_encoding con el parámetro 'auto' no funciona bien. Establecer mb_detect_order ('ASCII, UTF-8,JIS,EUC-JP,SJIS,EUC-KR, UHC') no ayuda ya que detectará EUC - * incorrectamente.

Llegué a la conclusión de que mientras las cadenas de entrada provengan de HTML, debería usar 'charset' en un elemento meta. Utilizo Simple HTML DOM Parser porque soporta HTML no válido.

El siguiente fragmento extrae elemento title de una página web. Si desea convertir toda la página, es posible que desee eliminar algunas líneas.

<?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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-09-14 23:29:02

Tuve el mismo problema con phpQuery (ISO-8859-1 en lugar de UTF-8 ) y este truco me ayudó:

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

mb_internal_encoding('UTF-8'), phpQuery::newDocumentHTML($html, 'utf-8'), mbstring.internal_encoding y otras manipulaciones no tomar ningún efecto.

 -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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-07-15 20:35:51

Inténtalo sin 'auto'

Es decir:

mb_detect_encoding($text)

En lugar de:

mb_detect_encoding($text, 'auto')

Puedes encontrar Más información aquí: 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-22 21:03:40