Tengo algunos textos que tienen varias codificaciones, por ejemplo, el siguiente texto tiene una codificación mixta de UTF-8 e ISO-8859-1:

محتوای میکس شده و بخش سالم

Pero quiero que todos estos se conviertan en UTF-8, eso significa que las secciones que tienen codificación UTF-8 a la izquierda, y las otras cadenas se convierten en UTF-8, por ejemplo, el texto anterior debe aparecer como:

محتوای میکس شده و بخش سالم

Usé diferentes formas, uso la función iconv en PHP y uso la siguiente clase:

https://github.com/neitanod/forceutf8

Pero ninguno de ellos me dio la salida correcta, y siempre alguna parte del texto se convierte en un signo de interrogación como ???????.

¿Cuál es la mejor manera de convertir la codificación mixta a UTF-8 sin ningún daño?

Editar:

Bytes de fila de texto mixto:

c399e280a6c398c2adc398c2aac399cb86c398c2a7c39bc59220c399e280a6c39bc592c39ac2a9c398c2b320c398c2b4c398c2afc399e280a120d98820d8a8d8aed8b420d8b3d8a7d984d985

Texto correcto:

محتوای میکس شده و بخش سالم
4
Morteza 23 feb. 2018 a las 15:50

2 respuestas

La mejor respuesta

Parte de su cadena es Windows-1252 mojibake, lo que significa que en algún momento una cadena UTF-8 se interpretó como Windows-1252 y se convirtió de esa suposición incorrecta a UTF-8. Eso se puede revertir transcodificando la cadena de UTF-8 a Windows-1252, lo que da como resultado la secuencia UTF-8 correcta del original. Para aplicar eso solo al subconjunto del texto que está desordenado, puede usar una expresión regular para, por ejemplo, aplicar la transformación solo a partes del texto que no sean árabes:

// sample data
$str_hex = 'c399e280a6c398c2adc398c2aac399cb86c398c2a7c39bc59220c399e280a6c39bc592c39ac2a9c398c2b320c398c2b4c398c2afc399e280a120d98820d8a8d8aed8b420d8b3d8a7d984d985';
// actual string
$str = hex2bin($str_hex);

echo 'Messed up: ', $str, PHP_EOL;  // محتوای میکس شده و بخش سالم

$fixed = preg_replace_callback(
    '/\\P{Arabic}+/u',  // matches non-Arabic sequences
    function (array $m) { return iconv('UTF-8', 'Windows-1252', $m[0]); }, 
    $str
);

echo 'Fixed: ', $fixed;  // محتوای میکس شده و بخش سالم
4
deceze 23 feb. 2018 a las 14:21

Con respecto a la respuesta de @Nulled que confirma que los datos provienen de una base de datos, puedo confirmar que el problema proviene de una codificación incorrecta de su tabla o base de datos. Tuve este problema antes y lo solucioné forzando la codificación de la base de datos / tabla antes de obtener mis datos usando esta consulta (debe actualizarla a la codificación de su base de datos / tabla):

SET NAMES latin1;

Por ejemplo:

$this->db->query('SET NAMES latin1;');
$this->db->query('SELECT * FROM table')->result();
-1
Oussama 23 feb. 2018 a las 13:54