UTF8?
UTF16?
Czy łańcuchy w PHP śledzą również używane kodowanie?
Spójrzmy na przykład na ten skrypt. Powiedz, że biegnę:
$original = "शक्नोम्यत्तुम्";
Co się właściwie dzieje?
Oczywiście myślę, że $original
nie będzie zawierać tylko 7 znaków. Te glify muszą być reprezentowane przez kilka bajtów.
Następnie robię:
$converted = mb_convert_encoding ($original , "UTF-8");
Co się stanie $converted
? Czym będzie $converted
się różnić $original
?
Czy będzie to dokładnie ta sama sekwencja bajtów, $original
ale z innym kodowaniem?
Odpowiedzi:
Łańcuch PHP jest tylko sekwencją bajtów, bez żadnego kodowania. Wartości łańcuchowe mogą pochodzić z różnych źródeł: klienta (przez HTTP), bazy danych, pliku lub literałów łańcuchowych w kodzie źródłowym. PHP czyta je wszystkie jako sekwencje bajtów i nigdy nie wyodrębnia żadnych informacji o kodowaniu.
Tak długo, jak wszystkie źródła danych i miejsca docelowe używają tego samego kodowania, najgorsze, co może się zdarzyć, to nieprawidłowe pozycje pozycji (jeśli używasz kodowania wielobajtowego), ponieważ PHP będzie liczyć bajty, a nie znaki.
Ale jeśli kodowania się nie zgadzają (np. Piszesz literał łańcuchowy w pliku źródłowym przechowywanym jako UTF-8, a następnie wysyłasz go do bazy danych, która oczekuje Latin-1), PHP nie wykona dla ciebie żadnej konwersji: wykona szczęśliwie skopiuj bajty na raw.
Najlepszym rozwiązaniem jest:
Content-type
nagłówków).SET NAMES UTF8
w MySQL).Dlaczego UTF-8? Ponieważ może reprezentować wszystkie znaki Unicode, a tym samym zastępuje wszystkie istniejące kodowania 7-bitowe i 8-bitowe oraz ponieważ jest binarnie zgodny z ASCII, to znaczy, każdy prawidłowy ciąg ASCII jest również prawidłowym ciągiem UTF-8 (ale nie vv .).
W twoim przykładzie tak się dzieje.
Najpierw zapisz plik źródłowy; Twój edytor tekstowy jest prawdopodobnie skonfigurowany do używania UTF-8, więc literał łańcuchowy kończy się kodowaniem UTF-8 na dysku. PHP czyta ten plik, interpretując ciąg znaków jako ciąg bajtów;
$original
teraz zawiera ciąg znaków zakodowany w UTF-8 składający się z 7 znaków, który jest tylko sekwencją bajtów (chociaż zawiera więcej niż 7 bajtów, ponieważ każdy znak jest reprezentowany przez dwa lub więcej bajtów). Jeśli następnie zadzwoniszecho $original
, zakodowany ciąg zostanie wysłany do klienta w niezmienionej postaci; jeśli powiedziałeś klientowi, aby spodziewał się UTF-8, wszystko jest w porządku, ale jeśli nie, PHP nie ma sposobu na odróżnienie, a skończysz na śmieciach w przeglądarce. W ramach eksperymentu spróbuj tego:strlen
jest agnostyczny dla kodowania i zakłada 8-bitowe kodowanie o stałej szerokości, to znaczy jeden bajt na znak, więc będzie liczyć bajty, a nie znaki.źródło