2012-01-16 34 views
22

Intento leer un archivo CSV y repetir el contenido. Pero el contenido muestra los caracteres incorrectos.Problemas de UTF-8 al leer el archivo CSV con fgetcsv

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

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

Este es el contenido del archivo CSV:

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

Mi script 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> 

He intentado utilizar setlocale(LC_ALL, 'de_DE.utf8'); como se sugiere here sin éxito. El contenido sigue siendo incorrecto.

¿Qué me falta?

Editar:

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

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?

+0

Qué pasa cuando file_get_contents eco ("specialchars.csv")? ¿Qué sucede cuando imprime_r (str_getcsv (reset (explode ("\ n", file_get_contents ("specialchars.csv"))), ';'))? – Furgas

+0

¡He actualizado mi pregunta! – testing

Respuesta

2

Ahora tengo que trabajar (después de quitar el comando header). Creo que el problema fue que la codificación del archivo php estaba en ISO-8859-1. Lo configuré en UTF-8 sin BOM. Pensé que ya lo había hecho, pero quizás hice un deshacer adicional.

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

+0

Si el archivo importado es de otro conjunto de caracteres que su código, es posible que también necesite setlocale(). – tim

6

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

<?php 

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

?> 
+1

Si pongo esto encima obtengo . – testing

+0

Quizás debería mencionar que cargué el archivo csv a través de un formulario con 'enctype =" multipart/form-data "accept-charset =" utf-8 "'. Si pongo tu código en el ejemplo, parece que funciona. – testing

3

El problema es que la función devuelve UTF-8 (puede verificar utilizando mb_detect_encoding), pero no convierte, y estos caracteres toman como UTF-8. Por lo tanto, es necesario hacer la conversió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 Inglés]

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

En mi caso particular, este funcionó. – Alliswell

10

detectado un problema similar: analizar el archivo CSV con caracteres especiales como E, E, O, etc. ...

La siguiente funcionaba bien para mí:

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

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

Con el fin de analizar todos los caracteres correctamente, he utilizado:

utf8_encode(fgets($file)); 

No te olvides de utilizar en todas las siguientes operaciones de cadena las 'Funciones de cadenas de múltiples bytes', como:

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

¡me has ahorrado mucho tiempo, gracias! He estado tratando de resolver este problema durante años ... –

+0

gracias, 'utf8_encode' hizo el truco para mí. – Latheesan

34

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>"; 
} 
?> 
+0

Esto ha ayudado. – jayarjo

+1

Esto eliminó por completo los caracteres especiales con espacio, lo cual es totalmente peligroso. –

+0

esto funcionó para mí – Edgar

1

En mi caso, el archivo de origen tiene windows-1250 de codificación y iconv grabados toneladas de avisos sobre caracteres no válidos en cadena de entrada ...

Así que 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 - str_getcsv uso en lugar de explotar - a causa de casos como este:

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

explotar va a explotar cadena en partes:

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

pero str_getcsv estallará cadena en partes:

some 
nice 
value 
and;here;comes;combinated;value 
and 
some 
others 
Cuestiones relacionadas