Pregunta

Intento leer un CSV y hacer eco del contenido. Pero el contenido muestra mal los caracteres.

Mäx Müstermänn -> Mö

La codificación del archivo CSV es UTF-8 sin BOM (verificado con Notepad ++).

Este es el contenido del archivo CSV:

"Mäx";"Müstermänn"

Mi guión PHP

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
<?php
$handle = fopen ("specialchars.csv","r");
echo '<table border="1"><tr><td>First name</td><td>Last name</td></tr><tr>';
while ($data = fgetcsv ($handle, 1000, ";")) {
        $num = count ($data);
        for ($c=0; $c < $num; $c++) {
            // output data
            echo "<td>$data[$c]</td>";
        }
        echo "</tr><tr>";
}
?>
</body>
</html>

Traté de usar setlocale(LC_ALL, 'de_DE.utf8'); Como se sugiere aquí sin éxito. El contenido todavía está mal mostrado.

¿Qué me estoy perdiendo?

Editar:

Un echo mb_detect_encoding($data[$c],'UTF-8'); me da UTF-8 UTF-8.

echo file_get_contents("specialchars.csv"); me da "Mäx";"Müstermänn".

Y

print_r(str_getcsv(reset(explode("\n", file_get_contents("specialchars.csv"))), ';'))

me da

Array ( [0] => Mäx [1] => Müstermänn )

¿Qué significa?

¿Fue útil?

Solución 6

Ahora lo tengo funcionando (después de quitar el header dominio). Creo que el problema era que la codificación del archivo PHP estaba en ISO-8859-1. Lo configuré en UTF-8 sin BOM. Pensé que ya había hecho eso, pero tal vez hice una deshacer adicional.

Además, usé SET NAMES 'utf8' para la base de datos. Ahora también es correcto en la base de datos.

Otros consejos

Prueba esto:

<?php
$handle = fopen ("specialchars.csv","r");
echo '<table border="1"><tr><td>First name</td><td>Last name</td></tr><tr>';
while ($data = fgetcsv ($handle, 1000, ";")) {
        $data = array_map("utf8_encode", $data); //added
        $num = count ($data);
        for ($c=0; $c < $num; $c++) {
            // output data
            echo "<td>$data[$c]</td>";
        }
        echo "</tr><tr>";
}
?>

Encontrado problema similar: analizar el archivo CSV con caracteres especiales como É, è, Ö, etc.

Lo siguiente funcionó bien para mí:

Para representar a los caracteres correctamente en la página HTML, se necesitaba el encabezado:

header('Content-Type: text/html; charset=UTF-8');

Para analizar correctamente cada personaje, utilicé:

utf8_encode(fgets($file));

No olvide usar en todas las operaciones de cadena siguiente las 'funciones de cadena multibyte', como:

mb_strtolower($value, 'UTF-8');

Intente poner esto en la parte superior de su archivo (antes de cualquier otra salida):

<?php

header('Content-Type: text/html; charset=UTF-8');

?>

El problema es que la función devuelve UTF-8 (puede verificar utilizando mb_detect_encoding), pero no convertir, y estos personajes toma como UTF-8. Por lo tanto, es necesario hacer la codificación inversa a la codificación inicial (Windows-1251 o CP1251) usando iconv. Pero ya que por el FGETCSV devuelve una matriz, sugiero escribir una función personalizada: [Lo siento por mi ingles]

function customfgetcsv(&$handle, $length, $separator = ';'){
    if (($buffer = fgets($handle, $length)) !== false) {
        return explode($separator, iconv("CP1251", "UTF-8", $buffer));
    }
    return false;
}

En mi caso, el archivo fuente tiene codificación Windows-1250 e Iconv imprime toneladas de avisos sobre caracteres ilegales en la cadena de entrada ...

Entonces esta solución me ayudó mucho:

/**
 * getting CSV array with UTF-8 encoding
 *
 * @param   resource    &$handle
 * @param   integer     $length
 * @param   string      $separator
 *
 * @return  array|false
 */
private function fgetcsvUTF8(&$handle, $length, $separator = ';')
{
    if (($buffer = fgets($handle, $length)) !== false)
    {
        $buffer = $this->autoUTF($buffer);
        return str_getcsv($buffer, $separator);
    }
    return false;
}

/**
 * automatic convertion windows-1250 and iso-8859-2 info utf-8 string
 *
 * @param   string  $s
 *
 * @return  string
 */
private function autoUTF($s)
{
    // detect UTF-8
    if (preg_match('#[\x80-\x{1FF}\x{2000}-\x{3FFF}]#u', $s))
        return $s;

    // detect WINDOWS-1250
    if (preg_match('#[\x7F-\x9F\xBC]#', $s))
        return iconv('WINDOWS-1250', 'UTF-8', $s);

    // assume ISO-8859-2
    return iconv('ISO-8859-2', 'UTF-8', $s);
}

Respuesta a la respuesta de @Manvel: use str_getcsv en lugar de explotar, debido a casos como este:

some;nice;value;"and;here;comes;combinated;value";and;some;others

Explode explotará la cadena en partes:

some
nice
value
"and
here
comes
combinated
value"
and
some
others

Pero str_getcsv explotará la cadena en partes:

some
nice
value
and;here;comes;combinated;value
and
some
others
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top