Wyjście PHP pokazujące małe czarne romby ze znakiem zapytania

81

Piszę program php, który pobiera ze źródła bazy danych. Niektóre z varcharów mają cudzysłowy, które są wyświetlane jako czarne diamenty ze znakiem zapytania ( , ZNAK ZAMIENNY , zakładam z tekstu Microsoft Word).

Jak mogę użyć php do usunięcia tych znaków?

hakre
źródło
1
Nie rozbierz ich, ustal czas. Zobacz także „czarny diament” na stackoverflow.com/questions/38363566/ ...
Rick James

Odpowiedzi:

74

Jeśli widzisz ten znak ( U + FFFD „REPLACEMENT CHARACTER”), zwykle oznacza to, że sam tekst jest zakodowany w jakiejś formie kodowania jednobajtowego, ale jest interpretowany w jednym z kodowań Unicode (UTF8 lub UTF16).

Gdyby było na odwrót, wyglądałoby (zwykle) mniej więcej tak: ä.

Prawdopodobnie oryginalne kodowanie to ISO-8859-1, znane również jako Latin-1. Możesz to sprawdzić bez konieczności zmiany skryptu: przeglądarki dają Ci możliwość ponownej interpretacji strony w innym kodowaniu - w przeglądarce Firefox użyj „Widok” -> „Kodowanie znaków”.

Aby przeglądarka używała właściwego kodowania, dodaj nagłówek HTTP w następujący sposób:

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

lub umieść kodowanie w metatagu:

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

Alternatywnie możesz spróbować odczytać z bazy danych w innym kodowaniu (najlepiej UTF-8) lub przekonwertować tekst z iconv().

DevilBoy
źródło
Jak dotąd jest to najbliższe rozwiązanie. Jednak teraz mam meta: <meta http-equiv = "Content-Type" content = "text / html; charset = UTF-8"> i używam iconv do konwersji z iso-8859-1 na utf- 8, znaki są teraz wyświetlane jako pudełko z 0096 i 0092 odpowiednio specjalnymi (lub -) innymi myślami?
tak, mam inną myśl: zrób trochę pracy domowej ... prawdopodobnie użyłeś niewłaściwego kodowania źródła. 0x92 i 0x96 to „zakrzywiony pojedynczy cudzysłów” i „myślnik” w systemie Windows-1252. czy to może być właściwe? wypróbowałeś sztuczkę z przeglądarką?
Nagłówek PHP rozwiązał problem podczas korzystania z klasy PDF2Text.
James P.,
Nie header("Content-Type: text/plain; charset=ISO-8859-1");powinno header("Content-Type: text/html; charset=ISO-8859-1");?
j08691
@ j08691: cóż, to zależy teraz od rodzaju treści, prawda?
41

To jest problem z kodowaniem znaków. W związku z tym mogło się to nie udać na wielu różnych poziomach, ale najprawdopodobniej ciągi znaków w Twojej bazie danych są zakodowane w formacie utf-8, a Ty prezentujesz je jako iso-8859-1. Albo na odwrót.

Właściwym sposobem rozwiązania tego problemu jest wyprostowanie zestawu postaci. Najprostszą strategią, ponieważ używasz PHP, jest używanie iso-8859-1 w całej aplikacji. Aby to zrobić, musisz upewnić się, że:

  • Wszystkie pliki źródłowe PHP są zapisywane jako iso-8859-1 (nie mylić z cp-1252).
  • Twój serwer WWW jest skonfigurowany do obsługi plików z rozszerzeniem charset=iso-8859-1
  • Alternatywnie możesz nadpisać ustawienia serwerów WWW z dokumentu PHP, używając header.
  • Ponadto użytkownik może wstawić meta-tag w was HTML, który określa to samo, ale nie jest to bezwzględnie konieczne.
  • Państwo może również określić accept-charsetatrybut swoich <form>elementów.
  • Tabele bazy danych są zdefiniowane z kodowaniem latin1
  • Połączenie z bazą danych między PHP a bazą danych jest ustawione na latin1

Jeśli masz już dane w swojej bazie danych, powinieneś mieć świadomość, że prawdopodobnie są już pomieszane. Jeśli nie jesteś jeszcze w fazie produkcji, po prostu wyczyść wszystko i zacznij od nowa. W przeciwnym razie będziesz musiał wykonać pewne czyszczenie danych.

Uwaga na temat metatagów, ponieważ wszyscy źle rozumieją, czym one są:

Kiedy serwer sieciowy wyświetla plik (dokument HTML), wysyła pewne informacje, które nie są prezentowane bezpośrednio w przeglądarce. Jest to znane jako nagłówki HTTP. Jednym z takich nagłówków jest Content-Typenagłówek, który określa typ MIME pliku (np. text/html), A także kodowanie (aka charset). Chociaż większość serwerów WWW wysyła Content-Typenagłówek z charsetinformacją, jest to opcjonalne. Jeśli go nie ma, przeglądarka zamiast tego zinterpretuje wszelkie metatagi z http-equiv="Content-Type". Należy pamiętać, że metatag jest interpretowany tylko wtedy, gdy serwer WWW nie wysyła nagłówka. W praktyce oznacza to, że jest używany tylko wtedy, gdy strona jest zapisana na dysku i stamtąd otwierana.

Ta strona zawiera bardzo dobre wyjaśnienie tych rzeczy.

troelskn
źródło
38

Ja też stanąłem przed tym problemem. W międzyczasie natknąłem się na trzy przypadki, w których to się stało:

  1. substr ()

    Używałem substr()na sznurku UTF8 które pocięte UTF8 znaków, zatem cięte znaków nie może być prawidłowo wyświetlane. Użyj mb_substr($utfstring, 0, 10, 'utf-8');zamiast tego. Kredyty

  2. htmlspecialchars ()

    Inny problem htmlspecialchars()dotyczył łańcucha UTF8. Poprawka polega na użyciu:htmlspecialchars($utfstring, ENT_QUOTES, 'UTF-8');

  3. preg_replace ()

    W końcu odkryłem, że preg_replace()może to prowadzić do problemów z UTF. Na $string = preg_replace('/[^A-Za-z0-9ÄäÜüÖöß]/', ' ', $string);przykład kod przekształcił łańcuch znaków UTF „F (×) = 2 × -3” na „F 2 ”. mb_ereg_replace()Zamiast tego należy użyć poprawki .

Mam nadzieję, że te dodatkowe informacje pomogą pozbyć się takich problemów.

Kai Noack
źródło
2
To był dokładnie problem, z którym miałem do czynienia. Nie wiedziałem o funkcjach ciągów MB.
Ren
1
Stało się to również dla strtolowerfunkcji. Wszystkie funkcje
opisane
13

Jak wspomniano we wcześniejszych odpowiedziach, dzieje się tak, ponieważ Twój tekst został zapisany w bazie danych w iso-8859-1kodowaniu lub w jakimkolwiek innym formacie.

Musisz więc po prostu przekonwertować dane utf8przed wyprowadzeniem.

$text = “string from database”;
$text = utf8_encode($text);
echo $text;
Hamlet Kraskian
źródło
11

Aby upewnić się, że połączenie MYSQL jest ustawione na UTF-8 (lub latin1, w zależności od tego, czego używasz), możesz to zrobić, aby:

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

lub użyj tego, aby sprawdzić, jakiego zestawu znaków używasz:

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

Więcej informacji tutaj: http://php.net/manual/en/function.mysql-set-charset.php

ptwiggerl
źródło
Było to bardzo przydatne i rozwiązało mój problem z kodowaniem cytatów w danych pochodzących ze zdalnej bazy danych MySQL, dziękuję!
tribulant
@ptwiggerl to bardzo pomogło.
unixmiah
Przeprowadziłem migrację strony internetowej na inny serwer i napotkałem ten problem, mysql_set_charset ('utf8', $ con); rozwiązałem to!
Rafael Moni
5

Opierając się na opisie problemu, dane w Twojej bazie danych są prawie na pewno zakodowane jako Windows-1252 , a Twoja strona prawie na pewno jest obsługiwana jako ISO-8859-1 . Te dwa zestawy znaków są równoważne, z wyjątkiem tego, że Windows-1252 ma 16 dodatkowych znaków, których nie ma w ISO-8859-1, w tym lewe i prawe cudzysłowy.

Zakładając, że moja analiza jest poprawna, najprostszym rozwiązaniem jest serwowanie Twojej strony jako Windows-1252. To zadziała, ponieważ wszystkie znaki w ISO-8859-1 są również w Windows-1252. W PHP możesz zmienić kodowanie w następujący sposób:

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

Jednak naprawdę powinieneś sprawdzić, jakiego kodowania znaków używasz w swoich plikach HTML i zawartości bazy danych, i zadbać o spójność lub poprawną konwersję, jeśli nie jest to możliwe.

Daniel Cassidy
źródło
Problem z tą sugestią polega na tym, że najprawdopodobniej dane są w tym momencie mieszanką różnych zestawów znaków. Jeśli nie wiesz dokładnie, co poszło nie tak, stanie się jeszcze bardziej bałagan, jeśli po prostu wrzucisz kilka losowych poprawek tu i tam.
troelskn
Zgadzam się. Zredagowałem nieco swój post, aby odzwierciedlić, że to rozwiązanie nie zastąpi wiedzy o tym, co robisz. Doszedłem jednak do wniosku, że większość programistów albo nie jest w stanie zrozumieć tego problemu, albo po prostu nie obchodzi. Wydaje się, że pojawia się co najmniej raz w miesiącu, gdy pracuję.
Daniel Cassidy,
To w dużej mierze moja obserwacja. Na czym mi zależy, zbierają, jak sieją. Ale prawdopodobnie masz rację; Są szanse, że jego dane to rzeczywiście cp-1252 .. Przynajmniej część z nich jest.
troelskn
Wypróbowałem kilka rozwiązań tego samego problemu. Ten był natychmiast skuteczny przy najmniejszym wysiłku
sześciostrunowy
4

Zdecydowałem się usunąć te znaki z ciągu, robiąc to -

ini_set('mbstring.substitute_character', "none"); 
$text= mb_convert_encoding($text, 'UTF-8', 'UTF-8');
DropHit
źródło
1
To jest niesamowite, zadziałało dla mnie, wypróbowałem również utf8_encode i ut8_decode - nie działały. Ale to rozwiązanie zadziałało w moim przypadku. Dziękuję Ci.
sanjeev shetty
4

Dodaj tę funkcję do swoich zmiennych utf8_encode ($ twoja zmienna);

rk_programmer
źródło
Proszę rozwinąć tę odpowiedź.
ppovoski
1
jest to funkcja, która pozwala usunąć znak specjalny i zwraca standard utf8 znaku google.com/…
rk_programmer
Działało to z ułamkami, które nie były wyświetlane poprawnie.
Rog
Moim zdaniem to powinna być akceptowana odpowiedź; jest to jedyna metoda, która działała dla mnie, wypróbowałem wszystkie.
quantme
4

Po prostu wklej ten kod na początku strony.

<?php
header("Content-Type: text/html; charset=ISO-8859-1");
?>
Harshil Kaneria
źródło
Dołącz krótkie wyjaśnienie, co robi kod.
CT Hall
1
Ten kod php zezwala na zestaw znaków „ISO-8859-1”, aw tym zestawie znaków ten symbol jest wyświetlany jako znak.
Harshil Kaneria
3

Spróbuj tego, proszę

mb_substr ($ opis, 0, 490, "UTF-8");

Vishal P Gothi
źródło
3

To ci pomoże. Umieść to w <head>tagu

<meta charset="iso-8859-1">
Prasant Kumar
źródło
1

Może to być spowodowane niedopasowaniem kodu Unicode lub innego zestawu znaków. Spróbuj zmienić zestaw znaków w przeglądarce, w ustawieniach tekst będzie wyglądał dobrze. Następnie pojawia się pytanie, jak przekonwertować zawartość bazy danych na zestaw znaków, którego używasz do wyświetlania. (Co w rzeczywistości może być po prostu dodaniem instrukcji charset utf-8 do wyjścia).

che
źródło
1

to, co ostatecznie zrobiłem po naprawieniu moich tabel, polegało na utworzeniu kopii zapasowej i zmianie ustawień na utf-8, a następnie zmieniłem plik zrzutu, aby DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci to moje wpisy zestawu znaków

teraz nie mam już problemów z zestawami znaków, ponieważ baza danych i przeglądarka to utf8.

Zrozumiałem, co to spowodowało. To była strona internetowa + efekty przeglądarki w DB. Na terminalach linuxowych (ubuntu + firefox) kodował bazę danych w latin1, czyli tak, jak ustawione są tabulatory. Ale w terminalach brzegowych systemu Windows 10 + wpisy były kodowane na siłę w utf8. Zauważyłem również, że Windows 10 ma problemy z utrzymaniem latin1, więc zdecydowałem się zgiąć z wiatrem i przekonwertować wszystko na utf8.

Pomyślałem, że to problem z Windows 10, ponieważ zaczęliśmy używać terminali win 10. więc po raz kolejny błędy Microsoft powodują problemy. Nadal nie wiem, dlaczego kodowanie zmienia się w formularzach, ponieważ przeglądarka w systemie Windows 10 pokazuje zestaw znaków latin1, ale kiedy przechodzi w kodowanie utf8 i otrzymuję anomalię danych. ale w linux + firefox to nie robi.

drtechno
źródło
1

To się udało w moim przypadku:

$text = utf8_decode($text)

Zamieniam czarny diament w znak zapytania, abyś mógł:

$text = str_replace('?', '', utf8_decode($text));
JacobRossDev
źródło
1
ostrzeżenie o $text = sekcji: spowoduje to zmianę wszystkich znaków zapytania w ciągu, a nie tylko diamentu
treyBake
1

Po prostu dodaj te wiersze przed nagłówkami.

Dokładny format .doc/docxplików zostanie pobrany:

 if(ini_get('zlib.output_compression'))

   ini_set('zlib.output_compression', 'Off');
 ob_clean();
asma
źródło
0

Możesz także zmienić zestaw znaków w przeglądarce. Tylko z powodów związanych z debugowaniem.

powtac
źródło
0

Używanie tego samego zestawu znaków (jak sugerowano tutaj) zarówno w bazie danych, jak i HTML nie zadziałało ... Pamiętając, że kod jest generowany jako HTML, zdecydowałem się użyć &quot;(kod HTML) lub &#34;(ISO Latin-1 code) w tekście mojej bazy danych, w którym zastosowano cudzysłowy. To rozwiązało problem, podając mi cudzysłów. To dziwne, że przed tym rozwiązaniem tylko niektóre cudzysłowy i apostrofy nie były wyświetlane poprawnie, podczas gdy inne działały, jednak specjalny kod działał we wszystkich przypadkach.

GrafixGuy
źródło
0

Uruchomiłem kod „wykrywania kodowania” po zmianie sortowania w phpmyadmin i teraz pojawia się on jako Latin_1.

ale oto coś, na co natknąłem się, patrząc na inną anomalię danych w mojej aplikacji i jak to naprawiłem:

Właśnie zaimportowałem tabelę z mieszanym kodowaniem (z rombowymi znakami zapytania w niektórych wierszach i wszystkie znajdowały się w tej samej kolumnie), więc oto mój kod poprawki. Użyłem procesu utf8_decode, który przyjmuje niezdefiniowany symbol zastępczy i przypisuje zwykły znak zapytania w miejsce „diamentowego znaku zapytania”, a następnie użyłem str_replace, aby zastąpić znak zapytania spacją między cudzysłowami. tutaj jest [kod]

    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
źródło
powyższy kod naprawia moją tabelę. ale radziłbym skomentować oświadczenia dotyczące aktualizacji, abyś mógł najpierw sprawdzić, czy ma to rozwiązać problem.
drtechno,
0

Do celów globalnych.

Zamiast konwertować, kodować, dekodować każdy tekst, wolę pozostawić je takimi, jakimi są i zamiast tego zmienić ustawienia php serwera. Więc,

  1. Niech diamenty

  2. W przeglądarce, w menu widoku wybierz „kodowanie tekstu” i znajdź takie, które pozwoli Ci zobaczyć Twój tekst poprawnie.

  3. Edytuj swój php.ini i dodaj:

    default_charset = "ISO-8859-1"

lub zamiast ISO-8859 ten, który pasuje do Twojego kodowania tekstu.

javier_domenech
źródło
0

Podczas wyodrębniania danych z dowolnego miejsca należy używać funkcji z przedrostkiem md_FUNC_NAME .

Miałem ten sam problem, który mi pomógł.

Możesz też znaleźć kod tego symbolu i użyć wyrażenia regularnego, aby usunąć te symbole.

Najlepszy twórca
źródło
-2

Przejdź do swojego phpmyadmin i wybierz swoją bazę danych i po prostu zwiększ długość / wartość pola tej tabeli do 500 lub 1000, to rozwiąże Twój problem.

Dheeraj Verma
źródło