Salida de PHP que muestra pequeños diamantes negros con un signo de interrogación

81

Estoy escribiendo un programa php que se extrae de una fuente de base de datos. Algunos de los varchars tienen citas que se muestran como diamantes negros con un signo de interrogación en ellos ( , CARÁCTER DE REEMPLAZO , supongo del texto de Microsoft Word).

¿Cómo puedo usar php para eliminar estos caracteres?

hakre
fuente
1
No los desnude, arregle el tiempo. Véase también "diamante negro" en stackoverflow.com/questions/38363566/…
Rick James

Respuestas:

74

Si ve ese carácter ( U + FFFD "CARÁCTER DE REEMPLAZO"), generalmente significa que el texto en sí está codificado en alguna forma de codificación de un solo byte pero interpretado en una de las codificaciones Unicode (UTF8 o UTF16).

Si fuera al revés, (normalmente) se vería así: ä.

Probablemente la codificación original sea ISO-8859-1, también conocida como Latin-1. Puede verificar esto sin tener que cambiar su secuencia de comandos: los navegadores le brindan la opción de volver a interpretar una página en una codificación diferente; en Firefox, use "Ver" -> "Codificación de caracteres".

Para que el navegador utilice la codificación correcta, agregue un encabezado HTTP como este:

header("Content-Type: text/html; charset=ISO-8859-1");

o poner la codificación en una metaetiqueta:

<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">

Alternativamente, puede intentar leer de la base de datos en otra codificación (UTF-8, preferiblemente) o convertir el texto con iconv().

Chico malo
fuente
Hasta ahora, esta es la solución más cercana. Sin embargo, ahora tengo un meta: <meta http-equiv = "Content-Type" content = "text / html; charset = UTF-8"> y estoy usando iconv para convertir de iso-8859-1 a utf- 8, los caracteres ahora se muestran como una caja con 0096 y 0092 respectivamente especiales ('o -) ¿algún otro pensamiento?
sí, tengo otro pensamiento: haz algunos deberes ... probablemente usaste la codificación de fuente incorrecta. 0x92 y 0x96 son "comillas simples curvas" y "guión" en windows-1252. ¿Podría ser el correcto? ¿Has probado el truco del navegador?
El encabezado PHP solucionó las cosas para mí cuando usaba la clase PDF2Text.
James P.
¿No debería header("Content-Type: text/plain; charset=ISO-8859-1");ser header("Content-Type: text/html; charset=ISO-8859-1");?
j08691
@ j08691: bueno, eso depende del tipo de contenido ahora, ¿no?
41

Este es un problema de juego de caracteres. Como tal, puede haber salido mal en muchos niveles diferentes, pero lo más probable es que las cadenas de su base de datos estén codificadas en utf-8 y las esté presentando como iso-8859-1. O al revés.

La forma correcta de solucionar este problema es aclarar los conjuntos de caracteres. La estrategia más simple, ya que está usando PHP, es usar iso-8859-1 en toda su aplicación. Para hacer esto, debe asegurarse de que:

  • Todos los archivos fuente de PHP se guardan como iso-8859-1 (no confundir con cp-1252).
  • Su servidor web está configurado para servir archivos con charset=iso-8859-1
  • Alternativamente, puede anular la configuración del servidor web desde dentro del documento PHP, usando header.
  • Además, puede insertar una metaetiqueta en su HTML, que especifique lo mismo, pero esto no es estrictamente necesario.
  • También puede especificar el accept-charsetatributo en sus <form>elementos.
  • Las tablas de la base de datos se definen con la codificación latin1
  • La conexión de la base de datos entre PHP y la base de datos está configurada en latin1

Si ya tiene datos en su base de datos, debe tener en cuenta que probablemente ya estén en mal estado. Si aún no está en la fase de producción, simplemente límpielo todo y comience de nuevo. De lo contrario, tendrá que hacer una limpieza de datos.

Una nota sobre las metaetiquetas, ya que todo el mundo entiende mal lo que son:

Cuando un servidor web sirve un archivo (un documento HTML), envía cierta información, que no se presenta directamente en el navegador. Esto se conoce como encabezados HTTP. Uno de esos encabezados es el Content-Typeencabezado, que especifica el tipo MIME del archivo (por ejemplo text/html), así como la codificación (también conocido como juego de caracteres). Si bien la mayoría de los servidores web envían un Content-Typeencabezado con charsetinformación, es opcional. Si no está presente, el navegador interpretará las metaetiquetas con http-equiv="Content-Type". Es importante darse cuenta de que la metaetiqueta solo se interpreta si el servidor web no envía el encabezado. En la práctica, esto significa que solo se usa si la página se guarda en el disco y luego se abre desde allí.

Esta página tiene una muy buena explicación de estas cosas.

troelskn
fuente
37

También me enfrenté a este problema. Mientras tanto, me encontré con tres casos en los que sucedió:

  1. substr ()

    Estaba usando substr()una cadena UTF8 que cortaba caracteres UTF8, por lo que los caracteres cortados no se podían mostrar correctamente. Úselo en su mb_substr($utfstring, 0, 10, 'utf-8');lugar. Créditos

  2. htmlspecialchars ()

    Otro problema fue el uso htmlspecialchars()de una cadena UTF8. La solución es usar:htmlspecialchars($utfstring, ENT_QUOTES, 'UTF-8');

  3. preg_replace ()

    Por último, descubrí que preg_replace()puede provocar problemas con UTF. El código, $string = preg_replace('/[^A-Za-z0-9ÄäÜüÖöß]/', ' ', $string);por ejemplo, transformó la cadena UTF "F (×) = 2 × -3" en "F 2 ". La solución es usar mb_ereg_replace()en su lugar.

Espero que esta información adicional ayude a solucionar estos problemas.

Kai Noack
fuente
2
Ese era exactamente el problema al que me enfrentaba. No sabía nada de las funciones de cadena de mb.
Ren
1
Sucedió también por strtolowerfunción. Todas las funciones involucradas en el manual de PHP
micaball
13

Como se mencionó en respuestas anteriores, está sucediendo porque su texto se ha escrito en la base de datos en iso-8859-1codificación o en cualquier otro formato.

Por lo tanto, solo necesita convertir los datos utf8antes de generarlos.

$text = “string from database”;
$text = utf8_encode($text);
echo $text;
Hamlet Kraskian
fuente
11

Para asegurarse de que su conexión MYSQL esté configurada en UTF-8 (o latin1, dependiendo de lo que esté usando), puede hacer esto para:

$con = mysql_connect("localhost","username","password");    
mysql_set_charset('utf8',$con);

o use esto para verificar qué juego de caracteres está usando:

$con = mysql_connect("localhost","username","password");   
$charset = mysql_client_encoding($con);
echo "The current character set is: $charset\n"; 

Más información aquí: http://php.net/manual/en/function.mysql-set-charset.php

ptwiggerl
fuente
Esto fue muy útil y resolvió mi problema de codificación de citas en datos provenientes de una base de datos MySQL remota, ¡gracias!
tribulante
@ptwiggerl esto ayudó mucho.
unixmiah
Migré un sitio web a otro servidor y me enfrenté a este problema, mysql_set_charset ('utf8', $ con); ¡resuelto!
Rafael Moni
5

Según su descripción del problema, es casi seguro que los datos de su base de datos estén codificados como Windows-1252 , y es casi seguro que su página se sirva como ISO-8859-1 . Estos dos juegos de caracteres son equivalentes, excepto que Windows-1252 tiene 16 caracteres adicionales que no están presentes en ISO-8859-1, incluidas las comillas rizadas izquierda y derecha.

Suponiendo que mi análisis sea correcto, la solución más simple es publicar su página como Windows-1252. Esto funcionará porque todos los caracteres que están en ISO-8859-1 también están en Windows-1252. En PHP puede cambiar la codificación de la siguiente manera:

header('Content-Type: text/html; charset=Windows-1252');

Sin embargo, debería comprobar qué codificación de caracteres está utilizando en sus archivos HTML y el contenido de su base de datos, y tener cuidado de ser coherente o convertir correctamente cuando esto no sea posible.

Daniel Cassidy
fuente
El problema con esta sugerencia es que lo más probable es que los datos sean una combinación de diferentes conjuntos de caracteres en este punto. Si no sabe exactamente qué salió mal, simplemente se vuelve aún más complicado, si solo agrega algunas correcciones al azar aquí y allá.
troelskn
Estoy de acuerdo. Edité mi publicación un poco para reflejar que esta solución no sustituye a saber lo que estás haciendo. Sin embargo, he llegado a la conclusión de que la mayoría de los desarrolladores son incapaces de comprender este problema o simplemente no les importa. Parece que surge al menos una vez al mes donde trabajo.
Daniel Cassidy
Esa también es mi observación. Por lo que a mí me importa, cosechan lo que siembran. Pero probablemente tengas razón; Lo más probable es que sus datos sean efectivamente cp-1252 .. Al menos algunos de ellos lo son.
troelskn
Probé varias soluciones para el mismo problema. Este fue inmediatamente efectivo con el menor esfuerzo
seis cuerdas
4

Elegí quitar estos caracteres de la cadena haciendo esto:

ini_set('mbstring.substitute_character', "none"); 
$text= mb_convert_encoding($text, 'UTF-8', 'UTF-8');
DropHit
fuente
1
Esto es increíble, funcionó para mí, probé utf8_encode y ut8_decode también, no funcionó. Pero esta solución funcionó en mi caso. Gracias.
sanjeev shetty
4

Agregue esta función a sus variables utf8_encode ($ su variable);

rk_programmer
fuente
Desarrolle esta respuesta.
ppovoski
1
esta es la función que le permite eliminar el carácter especial y le devuelve el estándar utf8 de carácter google.com/…
rk_programmer
Esto funcionó con fracciones que no se mostraban correctamente.
Rog
En mi opinión, esta debería ser una respuesta aceptada; este es el único método que funcionó para mí, lo probé todo.
quantme
4

Simplemente pegue este código desde el principio de la página.

<?php
header("Content-Type: text/html; charset=ISO-8859-1");
?>
Harshil Kaneria
fuente
Incluya una breve explicación de lo que hace el código.
CT Hall
1
Este código php permite el juego de caracteres "ISO-8859-1" y en este juego de caracteres este símbolo se muestra como un carácter.
Harshil Kaneria
3

Prueba esto por favor

mb_substr ($ descripción, 0, 490, "UTF-8");

Vishal P Gothi
fuente
3

Esto te ayudara. Pon esta <head>etiqueta interior

<meta charset="iso-8859-1">
Prasant Kumar
fuente
1

Eso puede ser causado por unicode u otro juego de caracteres que no coincida. Intente cambiar el juego de caracteres en su navegador, en la configuración el texto se verá bien. Entonces es cuestión de cómo convertir el contenido de su base de datos al juego de caracteres que usa para mostrar. (Lo que en realidad puede ser simplemente agregar una declaración de juego de caracteres utf-8 a su salida).

che
fuente
1

lo que terminé haciendo al final después de arreglar mis tablas fue hacer una copia de seguridad y volver a cambiar la configuración a utf-8, luego modifiqué mi archivo de volcado para que DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci son mis entradas de juego de caracteres

ahora ya no tengo problemas con el conjunto de caracteres porque la base de datos y el navegador son utf8.

Descubrí qué lo causó. Fue la página web + los efectos del navegador en la base de datos. En los terminales que son linux (ubuntu + firefox) estaba codificando la base de datos en latin1 que es lo que se establecen las tabes. Pero en los terminales de borde de Windows 10 +, las entradas se codificaron a la fuerza en utf8. También noté que Windows 10 tiene problemas para permanecer con latin1, así que decidí inclinarme con el viento y convertir todo a utf8.

Pensé que era un problema de Windows 10 porque comenzamos a usar terminales win 10. una vez más, los errores de microsoft causan problemas. Todavía no sé por qué cambia la codificación en los formularios porque el navegador en Windows 10 muestra el conjunto de caracteres latin1, pero cuando se codifica en utf8 y obtengo la anomalía de datos. pero en linux + firefox no hace eso.

drtechno
fuente
1

Esto pasó a funcionar en mi caso:

$text = utf8_decode($text)

Convierto el carácter de diamante negro en un signo de interrogación para que puedas:

$text = str_replace('?', '', utf8_decode($text));
JacobRossDev
fuente
1
advertencia sobre la $text = sección: esto cambiará todos los signos de interrogación dentro de la cadena, no solo el diamante
treyBake
1

Simplemente agregue estas líneas antes de los encabezados.

Se .doc/docxrecuperará el formato exacto de los archivos:

 if(ini_get('zlib.output_compression'))

   ini_set('zlib.output_compression', 'Off');
 ob_clean();
asma
fuente
0

También puede cambiar el conjunto de caracteres en su navegador. Solo por motivos de depuración.

Powtac
fuente
0

Usar el mismo juego de caracteres (como se sugiere aquí) tanto en la base de datos como en el HTML no me ha funcionado ... Entonces, recordando que el código se genera como HTML, elegí usar el &quot;(código HTML) o el &#34;(ISO Latin-1 código) en el texto de mi base de datos donde se usaron comillas. Esto resolvió el problema y me proporcionó un signo de comillas. Es extraño notar que antes de esta solución, solo algunas de las comillas y apóstrofos no se mostraban correctamente mientras que otras sí, sin embargo, el código especial funcionaba en todos los casos.

GrafixGuy
fuente
0

Ejecuté el código "detectar codificación" después de mi cambio de intercalación en phpmyadmin y ahora aparece como Latin_1.

pero aquí hay algo que encontré al buscar una anomalía de datos diferente en mi aplicación y cómo lo solucioné:

Acabo de importar una tabla que tiene codificación mixta (con signos de interrogación de diamante en algunas líneas, y todos estaban en la misma columna), así que aquí está mi código de corrección. Usé el proceso utf8_decode que toma el marcador de posición indefinido y asigna un signo de interrogación simple en el lugar del "signo de interrogación de diamante" y luego usé str_replace para reemplazar el signo de interrogación con un espacio entre comillas. aquí está el [código]

    include 'dbconnectfile.php';

  //// the variable $db comes from my db connect file
   /// inx is my auto increment column
   /// broke_column is the column I need to fix

      $qwy = "select inx,broke_column from Table ";
      $res = $db->query($qwy); 

      while ($data = $res->fetch_row()) {
      for ($m=0; $m<$res->field_count; $m++) {
           if ($m==0){ 
           $id=0;
           $id=$data[$m];
       echo $id;
           }else if ($m==1){ 
             $fix=0;
             $fix=$data[$m];


             $fix = utf8_decode($fix);
             $fixx =str_replace("?"," ",$fix);

        echo $fixx;

        ////I echoed the data to the screen because I like to see something as I execute it :)
            }
            }
         $insert= "UPDATE Table SET broke_column='".$fixx."'  where inx='".$id."'";
          $insresult= $db->query($insert);
      echo"<br>";
        }

        ?>        
drtechno
fuente
el código anterior arregla mi tabla. pero recomendaría comentar las declaraciones de actualización para que pueda ver primero si va a solucionar el problema.
drtechno
0

Para propósitos globales.

En lugar de convertir, codificar, decodificar cada texto, prefiero dejarlos como están y cambiar la configuración de php del servidor. Entonces,

  1. Deja que los diamantes

  2. Desde el navegador, en el menú de visualización, seleccione "codificación de texto" y busque la que le permita ver su texto correctamente.

  3. Edite su php.ini y agregue:

    default_charset = "ISO-8859-1"

o en lugar de ISO-8859, el que se ajuste a su codificación de texto.

javier_domenech
fuente
0

Cuando extrae datos de cualquier lugar, debe usar funciones con el prefijo md_FUNC_NAME.

Tuve el mismo problema que me ayudó.

O puede encontrar el código de este símbolo y usar regexp para eliminar estos símbolos.

Skylark Roman
fuente
-2

Vaya a su phpmyadmin y seleccione su base de datos y simplemente aumente la longitud / valor del campo de esa tabla a 500 o 1000, resolverá su problema.

Dheeraj Verma
fuente