UTF-8 można wykryć automatycznie lepiej na podstawie zawartości niż przy pomocy BOM. Metoda jest prosta: spróbuj odczytać plik (lub ciąg) jako UTF-8, a jeśli się powiedzie, załóż, że dane to UTF-8. W przeciwnym razie załóż, że jest to CP1252 (lub jakieś inne 8-bitowe kodowanie). Każde ośmiobitowe kodowanie inne niż UTF-8 prawie na pewno będzie zawierać sekwencje niedozwolone przez UTF-8. Czysty ASCII (7 bitów) jest interpretowany jako UTF-8, ale wynik również jest poprawny.
Tronic
39
Skanowanie dużych plików w poszukiwaniu zawartości UTF-8 zajmuje dużo czasu. LM sprawia, że ten proces jest znacznie szybszy. W praktyce często musisz wykonać jedno i drugie. Winowajcą jest obecnie to, że wciąż dużo treści tekstowych nie jest Unicode, a ja wciąż wpadam na narzędzia, które mówią, że robią Unicode (na przykład UTF-8), ale emitują swoją treść inną stronę kodową.
Jeroen Wiert Pluimers,
10
@Tronic Nie wydaje mi się, żeby „lepiej” pasowało w tym przypadku. To zależy od środowiska. Jeśli masz pewność, że wszystkie pliki UTF-8 są oznaczone BOM, to sprawdzenie BOM jest „lepszym” sposobem, ponieważ jest szybszy i bardziej niezawodny.
mg30rg
32
UTF-8 nie ma BOM. Kiedy umieścisz punkt kodowy U + FEFF na początku pliku UTF-8, musisz zachować szczególną ostrożność, aby sobie z tym poradzić. To tylko jedno z tych kłamstw związanych z nazewnictwem Microsoft, takich jak nazywanie kodowania „Unicode”, gdy nie ma czegoś takiego.
tchrist
7
"Nowoczesny Mainframe (i AIX) jest trochę endian UTF-8 świadomy" UTF-8 nie mają endedness ! nie ma tasowania bajtów, aby ustawić pary lub grupy czterech we właściwej „kolejności” dla określonego systemu! Aby wykryć sekwencję bajtów UTF-8, warto zauważyć, że pierwszy bajt „wielopunktowej” sekwencji kodowej (bajty, które NIE są „zwykłymi” kodami ASCII), ma ustawiony bit MS i wszystkie jeszcze jeden do trzech sukcesywnie mniej znaczące bity, po których następuje bit resetu. Całkowita liczba tych ustawionych bitów jest o jeden mniej bajtów w tym
punkcie kodowym
Odpowiedzi:
773
LM UTF-8 to sekwencja bajtów na początku strumienia tekstowego ( 0xEF, 0xBB, 0xBF), która pozwala czytelnikowi na bardziej wiarygodne odgadnięcie pliku zakodowanego w UTF-8.
Zwykle BOM jest używany do sygnalizowania endianowości kodowania, ale ponieważ endianowość nie ma znaczenia dla UTF-8, BOM jest niepotrzebny.
... Użycie BOM nie jest wymagane ani zalecane dla UTF-8, ale może wystąpić w kontekstach, w których dane UTF-8 są konwertowane z innych form kodowania, które używają BOM lub gdzie BOM jest używany jako podpis UTF-8 . Aby uzyskać więcej informacji, zobacz podsekcję „Bajtowy znak porządkowy” w rozdziale 16.8, Specjalne .
Może nie jest to zalecane, ale z mojego doświadczenia w konwersjach hebrajskich zestawienie komponentów jest czasami kluczowe dla rozpoznawania UTF-8 w programie Excel i może mieć znaczenie między Jibrish a hebrajskim
Matanya
26
Może nie jest to zalecane, ale dziwiło mi się w moim skrypcie PowerShell podczas próby wypisania „æøå”
Marius,
63
Bez względu na to, że nie jest to zalecane przez standard, jest to dozwolone i zdecydowanie wolę mieć coś, co może działać jako sygnatura UTF-8, zamiast alternatywnych założeń lub zgadywania. Oprogramowanie zgodne z Unicode powinno / musi być w stanie poradzić sobie z jego obecnością, więc osobiście zachęcam do korzystania z niego.
martineau
30
@ bames53: Tak, w idealnym świecie przechowywanie kodowania plików tekstowych jako metadanych systemu plików byłoby lepszym sposobem na zachowanie tego. Ale większość z nas żyjących w prawdziwym świecie nie może zmienić systemu plików systemów operacyjnych, na których uruchamiane są nasze programy - więc używanie niezależnej od platformy sygnatury BOM standardu Unicode wydaje się najlepszą i najbardziej praktyczną alternatywą IMHO.
martineau
34
@martineau Jeszcze wczoraj natknąłem się na plik z LM UTF-8, który nie był UTF-8 (był to CP936). Niefortunne jest to, że osoby odpowiedzialne za ogrom bólu spowodowanego przez BOM UTF-8 są w dużej mierze tego nieświadome.
bames53
243
Inne doskonałe odpowiedzi już odpowiedziały, że:
Nie ma oficjalnej różnicy między UTF-8 a BOM-ed UTF-8
Zmodyfikowany BOM ciąg UTF-8 rozpocznie się od trzech następujących bajtów. EF BB BF
Te bajty, jeśli występują, należy zignorować podczas wyodrębniania ciągu z pliku / strumienia.
Ale jako dodatkowa informacja do tego, BOM dla UTF-8 może być dobrym sposobem na „wąchanie”, jeśli łańcuch został zakodowany w UTF-8 ... Lub może być prawidłowym łańcuchem w dowolnym innym kodowaniu ...
Na przykład dane [EF BB BF 41 42 43] mogą być albo:
Więc chociaż fajnie jest rozpoznać kodowanie zawartości pliku, patrząc na pierwsze bajty, nie powinieneś na tym polegać, jak pokazano w powyższym przykładzie
@Alcott: Zrozumiałeś poprawnie. Ciąg [EF BB BF 41 42 43] to tylko kilka bajtów. Potrzebujesz informacji zewnętrznych, aby wybrać sposób ich interpretacji. Jeśli uważasz, że te bajty zostały zakodowane przy użyciu ISO-8859-1, to ciąg ma postać „ï» ¿ABC ”. Jeśli uważasz, że te bajty zostały zakodowane przy użyciu UTF-8, to jest to „ABC”. Jeśli nie wiesz, musisz spróbować się dowiedzieć. LM może być wskazówką. Brak nieprawidłowego znaku po zdekodowaniu jako UTF-8 może być kolejnym ... Ostatecznie, chyba że potrafisz jakoś zapamiętać / znaleźć kodowanie, tablica bajtów jest tylko tablicą bajtów.
paercebal,
19
@paercebal Chociaż „ï» ¿”jest poprawne Latin-1, bardzo mało prawdopodobne jest, aby plik tekstowy zaczynał się od tej kombinacji. To samo dotyczy markerów ucs2-le / be ÿþ i þÿ. Nigdy też nie możesz wiedzieć.
user877329,
16
@deceze Prawdopodobnie jest to niepoprawne językowo: Najpierw ï (co jest w porządku), a następnie jakiś cudzysłów bez spacji pomiędzy nimi (nie jest OK). ¿Oznacza, że jest hiszpański, ale ï nie jest używany w języku hiszpańskim. Wniosek: bez niego nie jest to latin-1 z pewnością znacznie przewyższającą pewność.
user877329,
20
@ użytkownik Pewnie, to niekoniecznie ma sens. Ale jeśli twój system polega na zgadywaniu , wtedy pojawiają się niepewności. Niektórzy złośliwi użytkownicy celowo przesyłają tekst zaczynając od tych 3 liter, a twój system nagle zakłada, że patrzy na UTF-8 z BOM, traktuje tekst jako UTF-8, gdzie powinien używać Latin-1 i ma miejsce wstrzyknięcie Unicode. Tylko hipotetyczny przykład, ale na pewno możliwy. Nie można oceniać kodowania tekstu na podstawie jego zawartości, kropki.
deceze
40
„Kodowania powinny być znane, a nie boskie”. Serce i dusza problemu. +1, dobry panie. Innymi słowy: albo ujednolic swoją treść i powiedz: „Zawsze używamy tego kodowania. Okres. Napisz w ten sposób. Przeczytaj w ten sposób” lub opracuj rozszerzony format, który umożliwia przechowywanie kodowania jako metadanych. (Ten ostatni prawdopodobnie również potrzebuje trochę „standardowego kodowania rozruchowego”. Jak powiedzenie „Część, która mówi ci o kodowaniu, to zawsze ASCII.”)
jpmc26
135
Istnieją co najmniej trzy problemy z umieszczeniem BOM w plikach zakodowanych w UTF-8.
Pliki, które nie zawierają tekstu, nie są już puste, ponieważ zawsze zawierają BOM.
Pliki zawierające tekst z podzestawu ASCII w UTF-8 same nie są już ASCII, ponieważ BOM nie jest ASCII, co powoduje awarię niektórych istniejących narzędzi i może być niemożliwe, aby użytkownicy zastąpili takie starsze narzędzia.
Nie można połączyć kilku plików razem, ponieważ każdy plik ma teraz BOM na początku.
I, jak wspomnieli inni, posiadanie BOM nie jest wystarczające ani konieczne do wykrycia, że coś jest UTF-8:
Nie jest to wystarczające, ponieważ może się zdarzyć, że dowolna sekwencja bajtów rozpocznie się od dokładnej sekwencji, która stanowi BOM.
Nie jest to konieczne, ponieważ możesz po prostu odczytać bajty tak, jakby były UTF-8; jeśli to się powiedzie, to z definicji jest to poprawny UTF-8.
Do punktu 1 „Pliki, które nie zawierają tekstu, nie są już puste, ponieważ zawsze zawierają BOM”, to (1) łączy poziom systemu plików OS z poziomem interpretowanej zawartości, a ponadto (2) niepoprawnie zakłada, że używając BOM należy umieścić LM także w każdym innym pustym pliku. Praktycznym rozwiązaniem (1) jest nie robienie (2). Zasadniczo skarga ogranicza się do „możliwe jest niepraktyczne umieszczenie BOM w innym pustym pliku, uniemożliwiając w ten sposób najłatwiejsze wykrycie logicznie pustego pliku (poprzez sprawdzenie rozmiaru pliku)”. Nadal dobre oprogramowanie powinno być w stanie sobie z tym poradzić, ponieważ ma cel.
Pozdrawiam i hth. - Alf
7
Odnośnie do punktu 2: „Pliki zawierające tekst ASCII nie są już same ASCII”, co łączy ASCII z UTF-8. Plik UTF-8 zawierający tekst ASCII to nie ASCII, to UTF-8. Podobnie plik UTF-16 zawierający tekst ASCII nie jest ASCII, lecz UTF-16. I tak dalej. ASCII to 7-bitowy jednobajtowy kod. UTF-8 jest 8-bitowym rozszerzeniem zmiennej długości ASCII. Jeśli „narzędzia psują się” z powodu wartości> 127, to po prostu nie nadają się do świata 8-bitowego. Jednym prostym praktycznym rozwiązaniem jest używanie tylko plików ASCII z narzędziami rozkładającymi się na wartości bajtów inne niż ASCII. Prawdopodobnie lepszym rozwiązaniem jest porzucenie tych niestosownych narzędzi.
Pozdrawiam i hth. - Alf
8
Punkt 3: „Nie można połączyć kilku plików razem, ponieważ każdy plik ma teraz BOM na początku” jest po prostu błędny. Nie mam problemu z połączeniem plików UTF-8 z BOM, więc jest to oczywiście możliwe. Myślę, że miałeś na myśli, że Unix-land catnie da ci czystego wyniku, który ma BOM dopiero na starcie. Jeśli miałeś to na myśli, to dlatego, że catdziała na poziomie bajtów, a nie na poziomie interpretowanej zawartości, i w podobny sposób catnie może poradzić sobie ze zdjęciami, powiedzmy. Nadal nie wyrządza to wiele szkody. Wynika to z faktu, że zestawienie komponentów koduje nieprzerwaną przestrzeń o zerowej szerokości.
Pozdrawiam i hth. - Alf
20
@ Cheersandhth.-Alf Ta odpowiedź jest poprawna. Wskazujesz tylko błędy Microsoft.
tchrist
9
@brighty: Sytuacja nie uległa poprawie poprzez dodanie BOM.
Deduplicator
84
Oto przykłady użycia BOM, które faktycznie powodują prawdziwe problemy, a jednak wiele osób nie wie o tym.
LM łamie skrypty
Skrypty powłoki, skrypty Perla, skrypty Python, skrypty Ruby, skrypty Node.js lub inne pliki wykonywalne, które muszą być uruchamiane przez interpreter - wszystko zaczyna się od linii shebang, która wygląda jak jedna z tych:
Informuje system, który interpreter musi zostać uruchomiony podczas wywoływania takiego skryptu. Jeśli skrypt jest zakodowany w UTF-8, można pokusić się o dołączenie BOM na początku. Ale tak naprawdę „#!” znaki to nie tylko znaki. W rzeczywistości są magiczną liczbą, która składa się z dwóch znaków ASCII. Jeśli umieścisz coś (np. LM) przed tymi znakami, plik będzie wyglądał, jakby miał inną magiczną liczbę i może to prowadzić do problemów.
Znaki shebang są reprezentowane przez te same dwa bajty w rozszerzonych kodowaniach ASCII, w tym UTF-8, który jest powszechnie używany w skryptach i innych plikach tekstowych w obecnych systemach uniksopodobnych. Pliki UTF-8 mogą jednak zaczynać się od opcjonalnego znaku kolejności bajtów (BOM); jeśli funkcja „exec” konkretnie wykrywa bajty 0x23 i 0x21, to obecność BOM (0xEF 0xBB 0xBF) przed shebang uniemożliwi wykonanie interpretera skryptu.Niektóre organy odradzają stosowanie znaku kolejności bajtów w skryptach POSIX (uniksopodobnych) [14] z tego powodu oraz ze względu na szerszą interoperacyjność i obawy filozoficzne. Ponadto znak kolejności bajtów nie jest konieczny w UTF-8, ponieważ kodowanie to nie ma problemów z endianowością; służy jedynie do identyfikacji kodowania jako UTF-8. [podkreślenie dodane]
Implementacje NIE MUSZĄ dodawać znaku kolejności bajtów na początku tekstu JSON.
BOM jest zbędny w JSON
Jest to nie tylko nielegalne w JSON, ale także nie jest potrzebne do określania kodowania znaków, ponieważ istnieją bardziej niezawodne sposoby jednoznacznego określenia zarówno kodowania znaków, jak i endianizmu używanych w dowolnym strumieniu JSON (szczegóły w tej odpowiedzi ).
BOM łamie parsery JSON
Jest nie tylko nielegalne w JSON i niepotrzebne , ale w rzeczywistości psuje całe oprogramowanie, które określa kodowanie przy użyciu metody przedstawionej w RFC 4627 :
Określanie kodowania i endianizmu JSON, badanie pierwszych czterech bajtów dla bajtu NUL:
00 00 00 xx - UTF-32BE
00 xx 00 xx - UTF-16BE
xx 00 00 00 - UTF-32LE
xx 00 xx 00 - UTF-16LE
xx xx xx xx - UTF-8
Teraz, jeśli plik zaczyna się od BOM, będzie wyglądał następująco:
00 00 FE FF - UTF-32BE
FE FF 00 xx - UTF-16BE
FF FE 00 00 - UTF-32LE
FF FE xx 00 - UTF-16LE
EF BB BF xx - UTF-8
Uwaga:
UTF-32BE nie zaczyna się od trzech wartości NUL, więc nie zostanie rozpoznany
UTF-32LE po pierwszym bajcie nie ma trzech wartości NUL, więc nie zostanie rozpoznany
UTF-16BE ma tylko jeden NUL w pierwszych czterech bajtach, więc nie zostanie rozpoznany
UTF-16LE ma tylko jeden NUL w pierwszych czterech bajtach, więc nie zostanie rozpoznany
W zależności od implementacji wszystkie z nich mogą być interpretowane niepoprawnie jako UTF-8, a następnie błędnie interpretowane lub odrzucane jako nieprawidłowe UTF-8 lub w ogóle nie rozpoznawane.
Dodatkowo, jeśli implementacja przetestuje poprawny JSON zgodnie z zaleceniem, odrzuci nawet dane wejściowe, które rzeczywiście są zakodowane jako UTF-8, ponieważ nie zaczynają się one od znaku ASCII <128, jak powinny zgodnie z RFC.
Inne formaty danych
BOM w JSON nie jest potrzebny, jest nielegalny i psuje oprogramowanie, które działa poprawnie zgodnie z RFC. Nobrainer powinien po prostu nie używać go wtedy, a jednak zawsze są ludzie, którzy nalegają na złamanie JSON za pomocą BOM, komentarzy, różnych reguł cytowania lub różnych typów danych. Oczywiście każdy może używać takich rzeczy jak BOM lub cokolwiek innego, jeśli potrzebujesz - po prostu nie nazywaj tego JSON.
W przypadku formatów danych innych niż JSON zobacz, jak to naprawdę wygląda. Jeśli jedynym kodowaniem jest UTF- *, a pierwszy znak musi być znakiem ASCII niższym niż 128, oznacza to, że masz już wszystkie informacje potrzebne do określenia zarówno kodowania, jak i endianiczności danych. Dodanie zestawień komponentów nawet jako funkcji opcjonalnej sprawiłoby, że byłoby to bardziej skomplikowane i podatne na błędy.
Inne zastosowania BOM
Jeśli chodzi o zastosowania poza JSON lub skryptami, myślę, że są już tutaj bardzo dobre odpowiedzi. Chciałem dodać bardziej szczegółowe informacje dotyczące skryptów i serializacji, ponieważ jest to przykład znaków BOM powodujących poważne problemy.
rfc7159, który zastępuje rfc4627, sugeruje, że obsługa BOM może nie być tak zła. Zasadniczo brak BOM to niejednoznaczna kludge, dzięki czemu stare oprogramowanie Windows i Unix, które nie rozpoznają Unicode, może nadal przetwarzać utf-8.
Eric Grange,
2
Wygląda na to, że JSON wymaga aktualizacji, aby go obsługiwać, podobnie jak skrypty Perla, skrypty Python, skrypty Ruby, Node.js. Tylko dlatego, że platformy te nie uwzględniają wsparcia, niekoniecznie zabija użycie BOM. Apple próbuje zabić Adobe od kilku lat, a Adobe wciąż jest w pobliżu. Ale pouczający post.
htm11h
13
@EricGrange, wydajesz się bardzo silnie wspierać BOM, ale nie zdajesz sobie sprawy, że dzięki temu wszechobecny, uniwersalnie użyteczny, optymalny minimalny format „zwykłego tekstu” będzie reliktem przeszłości sprzed UTF8! Dodanie dowolnego nagłówka (w paśmie) do zwykłego strumienia tekstowego z definicji narzuciłoby obowiązkowy protokół do najprostszych plików tekstowych, dzięki czemu nigdy więcej nie byłby „najprostszy”! I za jaki zysk? Aby obsługiwać wszystkie inne , starożytne kodowania CP, które również nie miały podpisów, więc możesz pomylić je z UTF-8? (BTW, ASCII też jest UTF-8. Więc też BOM dla tych?;) Chodź.)
Sz.
2
Ta odpowiedź jest powodem, dla którego wpadłem na to pytanie! Tworzę swoje skrypty bash w systemie Windows i mam wiele problemów z publikacją tych skryptów w systemie Linux! To samo dotyczy plików Jason.
Tono Nam
2
Chciałbym móc głosować tę odpowiedź około pięćdziesiąt razy. Chcę również dodać, że w tym momencie UTF-8 wygrał wojnę o standardy, a prawie cały tekst produkowany w Internecie to UTF-8. Niektóre najpopularniejsze języki programowania (takie jak C # i Java) używają UTF-16 wewnętrznie, ale gdy programiści używający tych języków zapisują pliki do strumieni wyjściowych, prawie zawsze kodują je jako UTF-8. Dlatego nie ma już sensu mieć BOM do oznaczania pliku UTF-8; UTF-8 powinien być domyślny, którego używasz podczas czytania, a wypróbować inne kodowania tylko w przypadku niepowodzenia dekodowania UTF-8.
rmunn
51
Czym różni się UTF-8 i UTF-8 bez BOM?
Krótka odpowiedź: w UTF-8 BOM jest kodowany jako bajty EF BB BFna początku pliku.
Długa odpowiedź:
Początkowo oczekiwano, że Unicode będzie kodowany w UTF-16 / UCS-2. BOM został zaprojektowany dla tej formy kodowania. Jeśli masz 2-bajtowe jednostki kodu, musisz wskazać, w jakiej kolejności znajdują się te dwa bajty, a powszechną konwencją do tego jest dołączanie znaku U + FEFF jako „Bajtowego znaku porządkowego” na początku danych. Znak U + FFFE jest trwale nieprzypisany, więc jego obecność może zostać użyta do wykrycia niewłaściwej kolejności bajtów.
UTF-8 ma tę samą kolejność bajtów niezależnie od endianizmu platformy, więc znak kolejności bajtów nie jest potrzebny. Może jednak wystąpić (jako sekwencja bajtów EF BB FF) w danych przekonwertowanych na UTF-8 z UTF-16 lub jako „sygnatura” wskazująca, że dane to UTF-8.
Który jest lepszy?
Bez. Jak odpowiedział Martin Cote, standard Unicode tego nie zaleca. Powoduje to problemy z oprogramowaniem nieobsługującym BOM.
Lepszym sposobem na wykrycie, czy plik to UTF-8, jest sprawdzenie poprawności. UTF-8 ma ścisłe reguły dotyczące tego, jakie sekwencje bajtów są poprawne, więc prawdopodobieństwo fałszywie dodatniego wyniku jest znikome. Jeśli sekwencja bajtów wygląda jak UTF-8, prawdopodobnie tak jest.
to również unieważniłoby poprawny UTF-8 z jednym błędnym bajtem, chociaż: /
endolith
8
-1 re „Powoduje problemy z oprogramowaniem nieobsługującym BOM.”, Nigdy nie było to dla mnie problemem, ale wręcz przeciwnie, brak BOM powoduje problemy z oprogramowaniem obsługującym BOM (w szczególności Visual C ++) był problem. Tak więc to stwierdzenie jest bardzo specyficzne dla platformy , wąskiego punktu widzenia dla systemów uniksowych, ale jest wprowadzane w błąd tak, jakby miało zastosowanie ogólnie. Które nie.
Pozdrawiam i hth. - Alf
6
Nie, UTF-8 nie ma BOM. Ta odpowiedź jest niepoprawna. Zobacz standard Unicode.
tchrist
2
Możesz nawet myśleć, że masz czysty plik ASCII, gdy patrzysz na bajty. Ale może to być również plik utf-16, w którym należy patrzeć na słowa, a nie bajty. Nowoczesne oprogramowanie powinno być świadome BOM. Wciąż odczytywanie utf-8 może się nie powieść, jeśli wykryje nieprawidłowe sekwencje, punkty kodowe, które mogą użyć mniejszej sekwencji lub punkty kodowe, które są odpowiednikami. Dla odczytu utf-16 może się również nie powieść, gdy istnieją osierocone surogaty.
wspaniały
1
@Af, nie zgadzam się z twoją interpretacją postawy innej niż BOM jako „ specyficznej dla platformy , wąskiego punktu widzenia z Unixem”. Dla mnie jedynym wąskim umysłem może być „ziemia uniksowa”, jeśli MS i Visual C ++ pojawią się przed * NIX, czego nie zrobili. Fakt, że MS (zakładam świadomie) zaczął używać LM w UTF-8, a nie UTF-16 sugeruje mi, że promowane zerwania sh, perl, g++oraz wiele innych wolnych i potężnych narzędzi. Chcesz, żeby coś działało? Wystarczy kupić wersje MS. MS stworzyło problem związany z platformą, podobnie jak katastrofa w swoim zakresie \ x80- \ x95.
bballdave025
30
UTF-8 z BOM jest lepiej identyfikowany. Doszedłem do tego wniosku na własnej skórze. Pracuję nad projektem, w którym jednym z wyników jest plik CSV zawierający znaki Unicode.
Jeśli plik CSV zostanie zapisany bez BOM, Excel uważa, że jest to ANSI i pokazuje bełkot. Po dodaniu „EF BB BF” z przodu (na przykład poprzez ponowne zapisanie go za pomocą Notatnika z UTF-8; lub Notepad ++ z UTF-8 z BOM), Excel otwiera go dobrze.
Dzięki za tę doskonałą wskazówkę na wypadek tworzenia plików UTF-8 do użytku przez program Excel. W innych okolicznościach nadal bym podążał za innymi odpowiedziami i pomijał BOM.
barfuin
5
Jest to również przydatne, jeśli tworzysz pliki zawierające tylko ASCII, a później mogą do niego zostać dodane pliki inne niż ascii. Właśnie natrafiłem na taki problem: oprogramowanie, które oczekuje utf8, tworzy plik z pewnymi danymi do edycji przez użytkownika. Jeśli plik początkowy zawiera tylko ASCII, jest otwierany w niektórych edytorach, a następnie zapisywany, kończy się na latin-1 i wszystko się psuje. Jeśli dodam BOM, edytor wykryje go jako UTF8 i wszystko działa.
Roberto Alsina,
1
Znalazłem wiele narzędzi związanych z programowaniem, które wymagają prawidłowego rozpoznawania plików UTF-8 przez BOM. Visual Studio, SSMS, SoureTree ....
kjbartel
5
Gdzie czytasz zalecenie używania BOM w tym RFC? Co najwyżej istnieje mocne zalecenie, aby nie zabraniać tego w pewnych okolicznościach, w których jest to trudne.
Deduplicator,
8
Excel myśli, że to ANSI i pokazuje bełkot, wtedy problem jest w Excelu.
Izaak
17
BOM ma tendencję do boomu (nie ma sensu (sic)) gdzieś, gdzieś. A kiedy hukuje (na przykład nie jest rozpoznawany przez przeglądarki, edytory itp.), Pojawia się jako dziwne znaki na początku dokumentu (na przykład plik HTML, odpowiedź JSON , RSS itp.) i powoduje rodzaj zawstydzeń, takich jak niedawny problem z kodowaniem, który wystąpił podczas rozmowy Obamy na Twitterze .
To bardzo denerwujące, gdy pojawia się w miejscach trudnych do debugowania lub gdy testy są zaniedbywane. Dlatego najlepiej go unikać, chyba że musisz go użyć.
Tak, spędziłem godziny na identyfikowaniu problemu spowodowanego kodowaniem pliku jako UTF-8 zamiast UTF-8 bez BOM. (Problem pojawił się tylko w IE7, co doprowadziło mnie do dość gęsiego pościgu. Użyłem „uwzględnienia” Django.)
user984003
Przyszli czytelnicy: zauważ, że wyżej wspomniany problem z tweetem nie był ściśle związany z BOM, ale gdyby tak było, tweet byłby zniekształcony w podobny sposób, ale na początku tweetu.
Halil Özgür
12
@ user984003 Nie, problem polega na tym, że Microsoft wprowadził cię w błąd. To, co nazywa UTF-8, nie jest UTF-8. To, co nazywa UTF-8 bez BOM, tak naprawdę jest UTF-8.
tchrist
co „sic” dodaje do „nie zamierzonej gry słów”
JoelFan,
2
@JoelFan Nie pamiętam już, ale myślę, że kalambur mógł być zamierzony pomimo twierdzenia autora :)
Halil Özgür
17
Pytanie: Czym różni się UTF-8 i UTF-8 bez BOM? Który jest lepszy?
Oto kilka fragmentów artykułu z Wikipedii na temat znaku kolejności bajtów (BOM), który moim zdaniem stanowi solidną odpowiedź na to pytanie.
Znaczenie BOM i UTF-8:
Standard Unicode zezwala na BOM w UTF-8 , ale nie wymaga ani nie zaleca jego używania. Kolejność bajtów nie ma znaczenia w UTF-8, więc jego jedynym zastosowaniem w UTF-8 jest zasygnalizowanie na początku, że strumień tekstowy jest kodowany w UTF-8.
Argument NIE używający BOM:
Podstawową motywacją do nieużywania BOM jest zgodność wsteczna z oprogramowaniem, które nie obsługuje Unicode ... Kolejną motywacją do nieużywania BOM jest zachęcenie UTF-8 jako „domyślnego” kodowania.
Argument ZA użyciem BOM:
Argumentem za użyciem BOM jest to, że bez niego konieczna jest analiza heurystyczna w celu ustalenia, jakiego znaku koduje plik. Historycznie taka analiza w celu rozróżnienia różnych kodowań 8-bitowych jest skomplikowana, podatna na błędy, a czasem powolna. Dostępnych jest wiele bibliotek ułatwiających zadanie, takich jak Mozilla Universal Charset Detector i International Components for Unicode.
Programiści błędnie zakładają, że wykrycie UTF-8 jest równie trudne (nie dzieje się tak, ponieważ znaczna większość sekwencji bajtów jest niepoprawna UTF-8, podczas gdy kodowania w tych bibliotekach próbują odróżnić wszystkie możliwe sekwencje bajtów). Dlatego nie wszystkie programy obsługujące Unicode przeprowadzają taką analizę i zamiast tego polegają na BOM.
W szczególności kompilatory i interpretatory Microsoft oraz wiele programów w systemie Microsoft Windows, takich jak Notatnik, nie będą poprawnie odczytywać tekstu UTF-8, chyba że będą miały tylko znaki ASCII lub zaczną się od BOM i dodają BOM na początku podczas zapisywania tekst jako UTF-8. Dokumenty Google dodają BOM, gdy dokument Microsoft Word zostanie pobrany jako zwykły plik tekstowy.
Na czym jest lepiej, Z lub BEZ BOM:
IETF zaleca jeśli protokół (a) zawsze używa UTF-8, lub (b) ma w jakiś inny sposób, aby wskazać kodowanie jest wykorzystywany, to powinna ona „zabronić korzystania z U + FEFF jako sygnatura.”
Mój wniosek:
Korzystaj z BOM tylko wtedy, gdy absolutnie niezbędna jest zgodność z aplikacją.
Zwróć też uwagę, że chociaż przywoływany artykuł z Wikipedii wskazuje, że wiele aplikacji Microsoft polega na BOM w celu prawidłowego wykrycia UTF-8, nie dotyczy to wszystkich aplikacji Microsoft. Na przykład, jak wskazał @barlop , podczas korzystania z wiersza polecenia systemu Windows z UTF-8 † , takie polecenia typei morenie oczekują obecności BOM. Jeśli zestawienie komponentów jest obecne, może być problematyczne, podobnie jak w przypadku innych aplikacji.
† chcpKomenda oferuje obsługę UTF-8 ( bez BOM) za pośrednictwem strony kodowej 65001 .
Lepiej będę surowo BYĆ BEZ BOM . Okazało się, że .htaccessi gzip compressionw połączeniu z UTF-8 BOM daje błąd kodowania Change do kodowania UTF-8 bez BOM obserwacji do sugestii, jak wyjaśniono tutaj rozwiązać problemy
Chetabahana
1
„Kolejną motywacją do niestosowania BOM jest zachęcenie UTF-8 jako„ domyślnego ”kodowania”. - Co jest tak silnym i uzasadnionym argumentem, że mógłbyś faktycznie zatrzymać tam odpowiedź! ...; -o Chyba że masz lepszy pomysł na uniwersalną reprezentację tekstu. ;) (Nie wiem, ile masz lat, ile lat musiałeś cierpieć w erze sprzed UTF8 (kiedy lingwiści desperacko rozważali nawet zmianę alfabetów), ale mogę ci powiedzieć, że z każdą sekundą zbliżamy się do pozbycia się bałagan wszystkich starożytnych kodowań jednobajtowych bez metadanych, zamiast posiadania „jednego” to czysta radość.)
Sz.
Zobacz także ten komentarz na temat tego, jak dodanie BOM (lub czegokolwiek!) Do najprostszych formatów plików tekstowych, „zwykły tekst”, oznaczałoby zapobieganie temu, aby najlepszy uniwersalny format kodowania tekstu był „zwykły” i „prosty” (tj. „overheadless”)! ...
Sz.
BOM jest głównie problematyczny w Linuksie, ponieważ wiele narzędzi tak naprawdę nie obsługuje Unicode (na przykład z radością skróci się w środkowych punktach kodowych). W przypadku większości innych współczesnych środowisk oprogramowania należy używać BOM, gdy kodowanie nie jest jednoznaczne (poprzez specyfikacje lub metadane).
Eric Grange,
9
To pytanie ma już milion odpowiedzi i wiele z nich jest całkiem dobrych, ale chciałem spróbować wyjaśnić, kiedy należy użyć BOM.
Jak wspomniano, jakiekolwiek użycie BOM UTF (Byte Order Mark) w celu ustalenia, czy ciąg znaków jest UTF-8, czy nie, jest wykształconym zgadywaniem. Jeśli dostępne są odpowiednie metadane (np. charset="utf-8"), To już wiesz, czego powinieneś używać, ale w przeciwnym razie musisz przetestować i przyjąć pewne założenia. Obejmuje to sprawdzenie, czy plik, z którego pochodzi łańcuch, zaczyna się od szesnastkowego kodu bajtowego EF BB BF.
Jeśli zostanie znaleziony kod bajtu odpowiadający BOM UTF-8, prawdopodobieństwo jest wystarczająco wysokie, aby założyć, że jest to UTF-8 i można stąd przejść. Gdy jednak zmuszony jest zgadnąć, dodatkowe sprawdzanie błędów podczas czytania nadal byłoby dobrym pomysłem na wypadek, gdyby coś się zniekształciło. Powinieneś założyć, że BOM nie jest UTF-8 (tj. Latin-1 lub ANSI), jeśli dane wejściowe zdecydowanie nie powinny być UTF-8 na podstawie jego źródła. Jeśli jednak nie ma BOM, możesz po prostu ustalić, czy ma to być UTF-8, sprawdzając poprawność względem kodowania.
Dlaczego BOM nie jest zalecany?
Oprogramowanie nieobsługujące kodu Unicode lub słabo zgodne może zakładać, że jest to Latin-1 lub ANSI i nie usunie BOM z łańcucha, co oczywiście może powodować problemy.
Nie jest to naprawdę potrzebne (po prostu sprawdź, czy zawartość jest zgodna i zawsze używaj UTF-8 jako rezerwowego, gdy nie można znaleźć zgodnego kodowania)
Kiedy należy kodować za pomocą BOM?
Jeśli nie możesz zarejestrować metadanych w żaden inny sposób (za pomocą znacznika charset lub meta systemu plików), a programy używane są jak BOM, powinieneś zakodować BOM. Jest to szczególnie prawdziwe w systemie Windows, w którym zakłada się, że wszystko bez BOM używa starszej strony kodowej. BOM informuje programy takie jak Office, że tak, tekst w tym pliku to Unicode; oto zastosowane kodowanie.
Jeśli chodzi o to, jedynymi plikami, z którymi naprawdę mam problemy, są CSV. W zależności od programu albo musi albo nie musi mieć BOM. Na przykład, jeśli używasz programu Excel 2007+ w systemie Windows, musisz go zakodować przy użyciu BOM, jeśli chcesz go płynnie otworzyć i nie musisz uciekać się do importowania danych.
Ostatnia część odpowiedzi jest w 100% poprawna: jedynym powodem użycia BOM jest konieczność współpracy z błędnym oprogramowaniem, które domyślnie nie używa UTF-8 do analizowania nieznanych plików.
rmunn
8
Należy zauważyć, że w przypadku niektórych plików BOM nie może mieć nawet w systemie Windows. Przykładami są SQL*pluslub VBScriptpliki. W przypadku, gdy takie pliki zawierają zestawienie komponentów, podczas próby ich wykonania pojawia się błąd.
UTF-8 z BOM pomaga tylko wtedy, gdy plik faktycznie zawiera niektóre znaki spoza ASCII. Jeśli jest dołączony i nie ma żadnych, prawdopodobnie spowoduje to uszkodzenie starszych aplikacji, które inaczej interpretowałyby plik jako zwykły ASCII. Te aplikacje na pewno zawiodą, gdy napotkają znak spoza ASCII, więc moim zdaniem BOM powinien zostać dodany tylko wtedy, gdy plik może i nie powinien być już interpretowany jako zwykły ASCII.
Chcę wyjaśnić, że wolę w ogóle nie mieć BOM. Dodaj go, jeśli niektóre stare śmieci zepsują się bez niego, a zastąpienie tej starszej aplikacji nie jest możliwe.
„Użycie BOM nie jest ani wymagane ani zalecane dla UTF-8, ale może wystąpić w kontekstach, w których dane UTF-8 są konwertowane z innych form kodowania, które używają BOM lub gdzie BOM jest używany jako podpis UTF-8”
Czy masz jakiś przykład, w którym oprogramowanie decyduje, czy użyć UTF-8 z / bez BOM, na podstawie tego, czy poprzednie kodowanie, z którego koduje, miało BOM, czy nie ?! To wydaje się absurdalne
Barlop
7
UTF-8 bez BOM nie ma BOM, co nie czyni go lepszym niż UTF-8 z BOM, z wyjątkiem sytuacji, gdy konsument pliku musi wiedzieć (lub chciałby wiedzieć), czy plik jest zakodowany w UTF-8 albo nie.
BOM jest zwykle przydatny do określenia endianowości kodowania, co nie jest wymagane w większości przypadków użycia.
Ponadto zestawienie komponentów może być niepotrzebnym hałasem / bólem dla tych konsumentów, którzy go nie znają lub nie dbają o niego, i może powodować dezorientację użytkowników.
„który nie ma zastosowania w przypadku UTF-8, ponieważ i tak ma 8 bitów na glif”. Eee ... nie, tylko glify ASCII-7 mają 8 bitów w UTF-8. Poza tym będzie to 16, 24 lub 32 bity.
Władca
3
„BOM jest zwykle przydatny do określenia endianowości kodowania, która nie jest wymagana w większości przypadków użycia.”… Endianness po prostu nie dotyczy UTF-8, niezależnie od przypadku użycia
JoelFan
6
Patrzę na to z innej perspektywy. Myślę, że UTF-8 z BOM jest lepszy, ponieważ dostarcza więcej informacji o pliku. Używam UTF-8 bez BOM tylko wtedy, gdy mam problemy.
Używam wielu języków (nawet cyrylicy ) na moich stronach przez długi czas, a kiedy pliki są zapisywane bez BOM i ponownie otwieram je do edycji w edytorze (jak zauważyli również cherouvim ), niektóre znaki są uszkodzone.
Zwróć uwagę, że klasyczny Notatnik systemu Windows automatycznie zapisuje pliki z BOM, gdy próbujesz zapisać nowo utworzony plik z kodowaniem UTF-8.
Osobiście zapisuję pliki skryptów po stronie serwera (.asp, .ini, .aspx) z plikami BOM i .html bez BOM .
Dziękujemy za doskonałą wskazówkę dotyczącą klasycznego Notatnika w systemie Windows. Spędziłem już trochę czasu, szukając dokładnie tego samego. Moim konsekwencją było zawsze używanie Notepad ++ zamiast klasycznego Windows Notatnika. :-)
barfuin
Lepiej użyj madedit. Jest to jedyny edytor, który - w trybie szesnastkowym - pokazuje jeden znak, jeśli wybierzesz sekwencję bajtów utf-8 zamiast podstawy 1: 1 między bajtem a znakiem. Edytor szesnastkowy, który zna plik UTF-8, powinien zachowywać się tak, jak robi to madedit!
wspaniały
@brighty Nie sądzę, że potrzebujesz jednego do jednego ze względu na BOM. to nie ma znaczenia, rozpoznanie BOM utf-8 to efbbbf lub fffe (fffe, jeśli źle odczytane). Można po prostu usunąć te bajty. Nie jest jednak źle mieć mapowanie reszty pliku, ale można też usunąć bajt po bajcie
barlop 03
@barlop Dlaczego chcesz usunąć LM utf-8, jeśli zawartość pliku jest zakodowana w utf-8? BOM jest rozpoznawany przez nowoczesne przeglądarki tekstu, kontrolki tekstu oraz edytory tekstu. Widok sekwencji utf-8 jeden do jednego nie ma sensu, ponieważ n bajtów daje jeden znak. Oczywiście edytor tekstowy lub edytor szesnastkowy powinien umożliwiać usunięcie dowolnego bajtu, ale może to prowadzić do nieprawidłowych sekwencji utf-8.
brighty
@brighty utf-8 z bom jest kodowaniem, a utf-8 bez bom jest kodowaniem. Polecenie cmd używa utf8 bez bom .. więc jeśli masz plik utf8, uruchom polecenie chcp 65001obsługi utf8, to utf8 bez bom. Jeśli to zrobisz type myfile, wyświetli się poprawnie tylko wtedy, gdy nie ma BOM. Jeśli zrobisz echo aaa>a.alub echo אאא>a.a wyślesz znaki do pliku aa, a chcesz chcieć 65001, wyśle to bez BOM.
barlop
6
Gdy chcesz wyświetlić informacje zakodowane w UTF-8, możesz nie mieć problemów. Zadeklaruj na przykład dokument HTML jako UTF-8, a wszystko w przeglądarce będzie wyświetlane w treści dokumentu.
Nie dzieje się tak jednak w przypadku plików tekstowych, CSV i XML, zarówno w systemie Windows, jak i Linux.
Na przykład plik tekstowy w systemie Windows lub Linux, jedna z najłatwiejszych rzeczy, jakie można sobie wyobrazić, nie jest to (zwykle) UTF-8.
Zapisz go jako XML i zadeklaruj jako UTF-8:
<?xml version="1.0" encoding="UTF-8"?>
Nie wyświetli się (nie zostanie odczytany) poprawnie, nawet jeśli zostanie zadeklarowany jako UTF-8.
Miałem ciąg danych zawierający francuskie litery, które należało zapisać jako XML do syndykacji. Bez tworzenia pliku UTF-8 od samego początku (zmiana opcji w IDE i „Utwórz nowy plik”) lub dodawanie BOM na początku pliku
$file="\xEF\xBB\xBF".$string;
Nie byłem w stanie zapisać francuskich liter w pliku XML.
FTM, w XML, myślę, że powinieneś zachować plik jako ASCII i zamiast tego używać encji .
Alois Mahdal
4
Wiem, że to stara odpowiedź, ale chcę tylko wspomnieć, że jest zła. Pliki tekstowe w systemie Linux (nie mogą mówić w innych systemach uniksowych) zwykle / are / UTF-8.
Functino,
6
Jedną praktyczną różnicą jest to, że jeśli napiszesz skrypt powłoki dla Mac OS X i zapiszesz go jako zwykły UTF-8, otrzymasz odpowiedź:
#!/bin/bash: No such file or directory
w odpowiedzi na linię shebang określającą, której powłoki chcesz użyć:
#!/bin/bash
Jeśli zapiszesz jako UTF-8, brak BOM (powiedzmy w BBEdit ) wszystko będzie dobrze.
To dlatego, że Microsoft zmienił znaczenie tego, co mówi standard. UTF-8 nie ma BOM: stworzyli Microsoft UTF-8, który wstawia fałszywy BOM przed strumieniem danych, a następnie powiedział, że nie, tak naprawdę jest to UTF-8. Nie jest. Po prostu rozszerza się i psuje.
tchrist
4
Jak wspomniano powyżej, UTF-8 z BOM może powodować problemy z oprogramowaniem nieobsługującym BOM (lub zgodnym). Kiedyś edytowałem pliki HTML zakodowane jako UTF-8 + BOM w opartym na Mozilli KompoZer , ponieważ klient wymagał programu WYSIWYG .
Niezmiennie układ zostanie zniszczony podczas zapisywania. Zajęło mi trochę czasu, żeby się tym zająć. Pliki te następnie działały dobrze w Firefoksie, ale pokazały dziwactwo CSS w Internet Explorerze, niszcząc układ. Po wielu godzinach majstrowania przy połączonych plikach CSS okazało się, że Internet Explorer nie lubił pliku HTML BOMfed. Nigdy więcej.
Właśnie znalazłem to w Wikipedii:
Znaki shebang są reprezentowane przez te same dwa bajty w rozszerzonych kodowaniach ASCII, w tym UTF-8, który jest powszechnie używany w skryptach i innych plikach tekstowych w obecnych systemach uniksopodobnych. Pliki UTF-8 mogą jednak zaczynać się od opcjonalnego znaku kolejności bajtów (BOM); jeśli funkcja „exec” konkretnie wykrywa bajty 0x23 0x21, to obecność BOM (0xEF 0xBB 0xBF) przed shebang uniemożliwi wykonanie interpretera skryptu. Niektóre organy odradzają stosowanie znaku kolejności bajtów w skryptach POSIX (uniksopodobnych) [15] z tego powodu oraz ze względu na szerszą interoperacyjność i obawy filozoficzne
Odp .: Oto kilka wskazówek, których należy przestrzegać:
Określony protokół (np. Konwencje Microsoft dla plików .txt) może wymagać użycia BOM w niektórych strumieniach danych Unicode, takich jak pliki. Jeśli musisz dostosować się do takiego protokołu, użyj BOM.
Niektóre protokoły zezwalają na opcjonalne LM w przypadku nieoznaczonego tekstu. W takich przypadkach
Tam, gdzie wiadomo, że strumień danych tekstowych to zwykły tekst, ale o nieznanym kodowaniu, BOM może być użyty jako podpis. Jeśli nie ma BOM, kodowanie może być cokolwiek.
Tam, gdzie wiadomo, że strumień danych tekstowych jest zwykłym tekstem Unicode (ale nie który endian), BOM może być użyty jako podpis. Jeśli nie ma BOM, tekst należy interpretować jako big-endian.
Niektóre protokoły bajtowe oczekują znaków ASCII na początku pliku. Jeśli UTF-8 jest używany z tymi protokołami, należy unikać korzystania z BOM jako podpisu formularza kodowania.
Tam, gdzie znany jest dokładny typ strumienia danych (np. Unicode big-endian lub Unicode little-endian), BOM nie powinien być używany. W szczególności, ilekroć strumień danych zostanie zadeklarowany jako UTF-16BE, UTF-16LE, UTF-32BE lub UTF-32LE, nie wolno używać BOM.
Znak kolejności bajtów (BOM) to znak Unicode używany do sygnalizowania endianizmu (kolejności bajtów) pliku tekstowego lub strumienia. Jego kod to U + FEFF. Użycie BOM jest opcjonalne i, jeśli jest używane, powinno pojawić się na początku strumienia tekstowego. Oprócz specyficznego zastosowania jako wskaźnika kolejności bajtów, znak BOM może również wskazywać, w której z kilku reprezentacji Unicode jest zakodowany tekst.
Zawsze użycie BOM w twoim pliku zapewni, że zawsze otworzy się poprawnie w edytorze obsługującym UTF-8 i BOM.
Mój prawdziwy problem z brakiem BOM jest następujący. Załóżmy, że mamy plik zawierający:
abc
Bez BOM jest to otwierane jako ANSI w większości edytorów. Tak więc inny użytkownik tego pliku otwiera go i dodaje niektóre znaki rodzime, na przykład:
abg-αβγ
Ups ... Teraz plik jest nadal w ANSI i zgadnij co, „αβγ” nie zajmuje 6 bajtów, ale 3. To nie jest UTF-8, a to powoduje inne problemy w późniejszym etapie łańcucha rozwoju.
Upewnij się, że na początku oprogramowania nieobsługującego BOM pojawiają się fałszywe bajty. Tak
Romain
1
@ Romain Muller: np. PHP 5 będzie zgłaszać błędy „niemożliwe” podczas próby wysłania nagłówków po BOM.
Piskvor opuścił budynek
5
αβγ nie jest ascii, ale może występować w kodowaniach opartych na 8bit-ascii. Użycie BOM wyłącza zaletę utf-8, jego kompatybilność z ascii (zdolność do pracy z aplikacjami lagacy, w których stosuje się czyste ascii).
ctrl-alt-delor
1
To zła odpowiedź. Sznurek z BOM przed nim to coś zupełnie innego. Nie powinno tam być i po prostu wszystko psuje.
tchrist
Bez BOM jest to otwierane jako ANSI w większości edytorów. Zgadzam się absolutnie. Jeśli tak się stanie, masz szczęście, jeśli masz do czynienia z poprawną stroną kodową, ale w rzeczywistości jest to tylko zgadywanie, ponieważ strona kodowa nie jest częścią pliku. BOM to.
wspaniały
1
Oto moje doświadczenia z wnioskami ściągania Visual Studio, Sourcetree i Bitbucket, co sprawiało mi pewne problemy:
Okazuje się, że BOM z podpisem będzie zawierać znak czerwonej kropki na każdym pliku podczas przeglądania żądania ściągnięcia (może to być dość denerwujące).
Jeśli najedziesz na niego kursorem, wyświetli się znak taki jak „ufeff”, ale okazuje się, że Sourcetree nie wyświetla tego typu znaków bajtowych, więc najprawdopodobniej skończy się na twoich żądaniach ściągania, co powinno być ok, ponieważ tak właśnie Visual Studio 2017 koduje teraz nowe pliki, więc może Bitbucket powinien to zignorować lub pokazać w inny sposób, więcej informacji tutaj:
UTF z BOM jest lepszy, jeśli używasz UTF-8 w plikach HTML i jeśli używasz serbskiej cyrylicy, serbskiej łaciny, niemieckiej, węgierskiej lub jakiegoś egzotycznego języka na tej samej stronie.
Tak oceniam (30 lat branży komputerowej i informatycznej).
Uważam, że to również prawda. Jeśli użyjesz znaków spoza pierwszego zestawu 255 ASCII i pominiesz BOM, przeglądarki interpretują go jako ISO-8859-1 i otrzymujesz zniekształcone znaki. Biorąc pod uwagę powyższe odpowiedzi, najwyraźniej producenci przeglądarek robią coś złego, gdy nie wykrywają BOM. Ale jeśli nie pracujesz w Microsoft Edge / Mozilla / Webkit / Blink, nie masz wyboru, ale pracujesz z wadami, które mają te aplikacje.
Odpowiedzi:
LM UTF-8 to sekwencja bajtów na początku strumienia tekstowego (
0xEF, 0xBB, 0xBF
), która pozwala czytelnikowi na bardziej wiarygodne odgadnięcie pliku zakodowanego w UTF-8.Zwykle BOM jest używany do sygnalizowania endianowości kodowania, ale ponieważ endianowość nie ma znaczenia dla UTF-8, BOM jest niepotrzebny.
Według standardu Unicode , BOM plików UTF-8 nie jest zalecane :
źródło
Inne doskonałe odpowiedzi już odpowiedziały, że:
EF BB BF
Ale jako dodatkowa informacja do tego, BOM dla UTF-8 może być dobrym sposobem na „wąchanie”, jeśli łańcuch został zakodowany w UTF-8 ... Lub może być prawidłowym łańcuchem w dowolnym innym kodowaniu ...
Na przykład dane [EF BB BF 41 42 43] mogą być albo:
Więc chociaż fajnie jest rozpoznać kodowanie zawartości pliku, patrząc na pierwsze bajty, nie powinieneś na tym polegać, jak pokazano w powyższym przykładzie
Kodowanie powinno być znane, a nie boskie.
źródło
Istnieją co najmniej trzy problemy z umieszczeniem BOM w plikach zakodowanych w UTF-8.
I, jak wspomnieli inni, posiadanie BOM nie jest wystarczające ani konieczne do wykrycia, że coś jest UTF-8:
źródło
cat
nie da ci czystego wyniku, który ma BOM dopiero na starcie. Jeśli miałeś to na myśli, to dlatego, żecat
działa na poziomie bajtów, a nie na poziomie interpretowanej zawartości, i w podobny sposóbcat
nie może poradzić sobie ze zdjęciami, powiedzmy. Nadal nie wyrządza to wiele szkody. Wynika to z faktu, że zestawienie komponentów koduje nieprzerwaną przestrzeń o zerowej szerokości.Oto przykłady użycia BOM, które faktycznie powodują prawdziwe problemy, a jednak wiele osób nie wie o tym.
LM łamie skrypty
Skrypty powłoki, skrypty Perla, skrypty Python, skrypty Ruby, skrypty Node.js lub inne pliki wykonywalne, które muszą być uruchamiane przez interpreter - wszystko zaczyna się od linii shebang, która wygląda jak jedna z tych:
Informuje system, który interpreter musi zostać uruchomiony podczas wywoływania takiego skryptu. Jeśli skrypt jest zakodowany w UTF-8, można pokusić się o dołączenie BOM na początku. Ale tak naprawdę „#!” znaki to nie tylko znaki. W rzeczywistości są magiczną liczbą, która składa się z dwóch znaków ASCII. Jeśli umieścisz coś (np. LM) przed tymi znakami, plik będzie wyglądał, jakby miał inną magiczną liczbę i może to prowadzić do problemów.
Patrz Wikipedia, artykuł: Shebang, sekcja: Magiczny numer :
BOM jest nielegalny w JSON
Patrz RFC 7159, sekcja 8.1 :
BOM jest zbędny w JSON
Jest to nie tylko nielegalne w JSON, ale także nie jest potrzebne do określania kodowania znaków, ponieważ istnieją bardziej niezawodne sposoby jednoznacznego określenia zarówno kodowania znaków, jak i endianizmu używanych w dowolnym strumieniu JSON (szczegóły w tej odpowiedzi ).
BOM łamie parsery JSON
Jest nie tylko nielegalne w JSON i niepotrzebne , ale w rzeczywistości psuje całe oprogramowanie, które określa kodowanie przy użyciu metody przedstawionej w RFC 4627 :
Określanie kodowania i endianizmu JSON, badanie pierwszych czterech bajtów dla bajtu NUL:
Teraz, jeśli plik zaczyna się od BOM, będzie wyglądał następująco:
Uwaga:
W zależności od implementacji wszystkie z nich mogą być interpretowane niepoprawnie jako UTF-8, a następnie błędnie interpretowane lub odrzucane jako nieprawidłowe UTF-8 lub w ogóle nie rozpoznawane.
Dodatkowo, jeśli implementacja przetestuje poprawny JSON zgodnie z zaleceniem, odrzuci nawet dane wejściowe, które rzeczywiście są zakodowane jako UTF-8, ponieważ nie zaczynają się one od znaku ASCII <128, jak powinny zgodnie z RFC.
Inne formaty danych
BOM w JSON nie jest potrzebny, jest nielegalny i psuje oprogramowanie, które działa poprawnie zgodnie z RFC. Nobrainer powinien po prostu nie używać go wtedy, a jednak zawsze są ludzie, którzy nalegają na złamanie JSON za pomocą BOM, komentarzy, różnych reguł cytowania lub różnych typów danych. Oczywiście każdy może używać takich rzeczy jak BOM lub cokolwiek innego, jeśli potrzebujesz - po prostu nie nazywaj tego JSON.
W przypadku formatów danych innych niż JSON zobacz, jak to naprawdę wygląda. Jeśli jedynym kodowaniem jest UTF- *, a pierwszy znak musi być znakiem ASCII niższym niż 128, oznacza to, że masz już wszystkie informacje potrzebne do określenia zarówno kodowania, jak i endianiczności danych. Dodanie zestawień komponentów nawet jako funkcji opcjonalnej sprawiłoby, że byłoby to bardziej skomplikowane i podatne na błędy.
Inne zastosowania BOM
Jeśli chodzi o zastosowania poza JSON lub skryptami, myślę, że są już tutaj bardzo dobre odpowiedzi. Chciałem dodać bardziej szczegółowe informacje dotyczące skryptów i serializacji, ponieważ jest to przykład znaków BOM powodujących poważne problemy.
źródło
Krótka odpowiedź: w UTF-8 BOM jest kodowany jako bajty
EF BB BF
na początku pliku.Długa odpowiedź:
Początkowo oczekiwano, że Unicode będzie kodowany w UTF-16 / UCS-2. BOM został zaprojektowany dla tej formy kodowania. Jeśli masz 2-bajtowe jednostki kodu, musisz wskazać, w jakiej kolejności znajdują się te dwa bajty, a powszechną konwencją do tego jest dołączanie znaku U + FEFF jako „Bajtowego znaku porządkowego” na początku danych. Znak U + FFFE jest trwale nieprzypisany, więc jego obecność może zostać użyta do wykrycia niewłaściwej kolejności bajtów.
UTF-8 ma tę samą kolejność bajtów niezależnie od endianizmu platformy, więc znak kolejności bajtów nie jest potrzebny. Może jednak wystąpić (jako sekwencja bajtów
EF BB FF
) w danych przekonwertowanych na UTF-8 z UTF-16 lub jako „sygnatura” wskazująca, że dane to UTF-8.Bez. Jak odpowiedział Martin Cote, standard Unicode tego nie zaleca. Powoduje to problemy z oprogramowaniem nieobsługującym BOM.
Lepszym sposobem na wykrycie, czy plik to UTF-8, jest sprawdzenie poprawności. UTF-8 ma ścisłe reguły dotyczące tego, jakie sekwencje bajtów są poprawne, więc prawdopodobieństwo fałszywie dodatniego wyniku jest znikome. Jeśli sekwencja bajtów wygląda jak UTF-8, prawdopodobnie tak jest.
źródło
sh
,perl
,g++
oraz wiele innych wolnych i potężnych narzędzi. Chcesz, żeby coś działało? Wystarczy kupić wersje MS. MS stworzyło problem związany z platformą, podobnie jak katastrofa w swoim zakresie \ x80- \ x95.UTF-8 z BOM jest lepiej identyfikowany. Doszedłem do tego wniosku na własnej skórze. Pracuję nad projektem, w którym jednym z wyników jest plik CSV zawierający znaki Unicode.
Jeśli plik CSV zostanie zapisany bez BOM, Excel uważa, że jest to ANSI i pokazuje bełkot. Po dodaniu „EF BB BF” z przodu (na przykład poprzez ponowne zapisanie go za pomocą Notatnika z UTF-8; lub Notepad ++ z UTF-8 z BOM), Excel otwiera go dobrze.
Przygotowanie znaku BOM do plików tekstowych Unicode jest zalecane przez RFC 3629: „UTF-8, format transformacji ISO 10646”, listopad 2003 na stronie http://tools.ietf.org/html/rfc3629 (ta ostatnia informacja znajduje się na: http://www.herongyang.com/Unicode/Notepad-Byte-Order-Mark-BOM-FEFF-EFBBBF.html )
źródło
BOM ma tendencję do boomu (nie ma sensu (sic)) gdzieś, gdzieś. A kiedy hukuje (na przykład nie jest rozpoznawany przez przeglądarki, edytory itp.), Pojawia się jako dziwne znaki

na początku dokumentu (na przykład plik HTML, odpowiedź JSON , RSS itp.) i powoduje rodzaj zawstydzeń, takich jak niedawny problem z kodowaniem, który wystąpił podczas rozmowy Obamy na Twitterze .To bardzo denerwujące, gdy pojawia się w miejscach trudnych do debugowania lub gdy testy są zaniedbywane. Dlatego najlepiej go unikać, chyba że musisz go użyć.
źródło
Oto kilka fragmentów artykułu z Wikipedii na temat znaku kolejności bajtów (BOM), który moim zdaniem stanowi solidną odpowiedź na to pytanie.
Znaczenie BOM i UTF-8:
Argument NIE używający BOM:
Argument ZA użyciem BOM:
Na czym jest lepiej, Z lub BEZ BOM:
Mój wniosek:
Korzystaj z BOM tylko wtedy, gdy absolutnie niezbędna jest zgodność z aplikacją.
Zwróć też uwagę, że chociaż przywoływany artykuł z Wikipedii wskazuje, że wiele aplikacji Microsoft polega na BOM w celu prawidłowego wykrycia UTF-8, nie dotyczy to wszystkich aplikacji Microsoft. Na przykład, jak wskazał @barlop , podczas korzystania z wiersza polecenia systemu Windows z UTF-8 † , takie polecenia
type
imore
nie oczekują obecności BOM. Jeśli zestawienie komponentów jest obecne, może być problematyczne, podobnie jak w przypadku innych aplikacji.†
chcp
Komenda oferuje obsługę UTF-8 ( bez BOM) za pośrednictwem strony kodowej 65001 .źródło
.htaccess
igzip compression
w połączeniu z UTF-8 BOM daje błąd kodowania Change do kodowania UTF-8 bez BOM obserwacji do sugestii, jak wyjaśniono tutaj rozwiązać problemyTo pytanie ma już milion odpowiedzi i wiele z nich jest całkiem dobrych, ale chciałem spróbować wyjaśnić, kiedy należy użyć BOM.
Jak wspomniano, jakiekolwiek użycie BOM UTF (Byte Order Mark) w celu ustalenia, czy ciąg znaków jest UTF-8, czy nie, jest wykształconym zgadywaniem. Jeśli dostępne są odpowiednie metadane (np.
charset="utf-8"
), To już wiesz, czego powinieneś używać, ale w przeciwnym razie musisz przetestować i przyjąć pewne założenia. Obejmuje to sprawdzenie, czy plik, z którego pochodzi łańcuch, zaczyna się od szesnastkowego kodu bajtowego EF BB BF.Jeśli zostanie znaleziony kod bajtu odpowiadający BOM UTF-8, prawdopodobieństwo jest wystarczająco wysokie, aby założyć, że jest to UTF-8 i można stąd przejść. Gdy jednak zmuszony jest zgadnąć, dodatkowe sprawdzanie błędów podczas czytania nadal byłoby dobrym pomysłem na wypadek, gdyby coś się zniekształciło. Powinieneś założyć, że BOM nie jest UTF-8 (tj. Latin-1 lub ANSI), jeśli dane wejściowe zdecydowanie nie powinny być UTF-8 na podstawie jego źródła. Jeśli jednak nie ma BOM, możesz po prostu ustalić, czy ma to być UTF-8, sprawdzając poprawność względem kodowania.
Dlaczego BOM nie jest zalecany?
Kiedy należy kodować za pomocą BOM?
Jeśli nie możesz zarejestrować metadanych w żaden inny sposób (za pomocą znacznika charset lub meta systemu plików), a programy używane są jak BOM, powinieneś zakodować BOM. Jest to szczególnie prawdziwe w systemie Windows, w którym zakłada się, że wszystko bez BOM używa starszej strony kodowej. BOM informuje programy takie jak Office, że tak, tekst w tym pliku to Unicode; oto zastosowane kodowanie.
Jeśli chodzi o to, jedynymi plikami, z którymi naprawdę mam problemy, są CSV. W zależności od programu albo musi albo nie musi mieć BOM. Na przykład, jeśli używasz programu Excel 2007+ w systemie Windows, musisz go zakodować przy użyciu BOM, jeśli chcesz go płynnie otworzyć i nie musisz uciekać się do importowania danych.
źródło
Należy zauważyć, że w przypadku niektórych plików BOM nie może mieć nawet w systemie Windows. Przykładami są
SQL*plus
lubVBScript
pliki. W przypadku, gdy takie pliki zawierają zestawienie komponentów, podczas próby ich wykonania pojawia się błąd.źródło
UTF-8 z BOM pomaga tylko wtedy, gdy plik faktycznie zawiera niektóre znaki spoza ASCII. Jeśli jest dołączony i nie ma żadnych, prawdopodobnie spowoduje to uszkodzenie starszych aplikacji, które inaczej interpretowałyby plik jako zwykły ASCII. Te aplikacje na pewno zawiodą, gdy napotkają znak spoza ASCII, więc moim zdaniem BOM powinien zostać dodany tylko wtedy, gdy plik może i nie powinien być już interpretowany jako zwykły ASCII.
Chcę wyjaśnić, że wolę w ogóle nie mieć BOM. Dodaj go, jeśli niektóre stare śmieci zepsują się bez niego, a zastąpienie tej starszej aplikacji nie jest możliwe.
Nie każ niczego oczekiwać BOM dla UTF-8.
źródło
Cytat na dole strony Wikipedii na BOM: http://en.wikipedia.org/wiki/Byte-order_mark#cite_note-2
źródło
UTF-8 bez BOM nie ma BOM, co nie czyni go lepszym niż UTF-8 z BOM, z wyjątkiem sytuacji, gdy konsument pliku musi wiedzieć (lub chciałby wiedzieć), czy plik jest zakodowany w UTF-8 albo nie.
BOM jest zwykle przydatny do określenia endianowości kodowania, co nie jest wymagane w większości przypadków użycia.
Ponadto zestawienie komponentów może być niepotrzebnym hałasem / bólem dla tych konsumentów, którzy go nie znają lub nie dbają o niego, i może powodować dezorientację użytkowników.
źródło
Patrzę na to z innej perspektywy. Myślę, że UTF-8 z BOM jest lepszy, ponieważ dostarcza więcej informacji o pliku. Używam UTF-8 bez BOM tylko wtedy, gdy mam problemy.
Używam wielu języków (nawet cyrylicy ) na moich stronach przez długi czas, a kiedy pliki są zapisywane bez BOM i ponownie otwieram je do edycji w edytorze (jak zauważyli również cherouvim ), niektóre znaki są uszkodzone.
Zwróć uwagę, że klasyczny Notatnik systemu Windows automatycznie zapisuje pliki z BOM, gdy próbujesz zapisać nowo utworzony plik z kodowaniem UTF-8.
Osobiście zapisuję pliki skryptów po stronie serwera (.asp, .ini, .aspx) z plikami BOM i .html bez BOM .
źródło
chcp 65001
obsługi utf8, to utf8 bez bom. Jeśli to zrobisztype myfile
, wyświetli się poprawnie tylko wtedy, gdy nie ma BOM. Jeśli zrobiszecho aaa>a.a
lubecho אאא>a.a
wyślesz znaki do pliku aa, a chcesz chcieć 65001, wyśle to bez BOM.Gdy chcesz wyświetlić informacje zakodowane w UTF-8, możesz nie mieć problemów. Zadeklaruj na przykład dokument HTML jako UTF-8, a wszystko w przeglądarce będzie wyświetlane w treści dokumentu.
Nie dzieje się tak jednak w przypadku plików tekstowych, CSV i XML, zarówno w systemie Windows, jak i Linux.
Na przykład plik tekstowy w systemie Windows lub Linux, jedna z najłatwiejszych rzeczy, jakie można sobie wyobrazić, nie jest to (zwykle) UTF-8.
Zapisz go jako XML i zadeklaruj jako UTF-8:
Nie wyświetli się (nie zostanie odczytany) poprawnie, nawet jeśli zostanie zadeklarowany jako UTF-8.
Miałem ciąg danych zawierający francuskie litery, które należało zapisać jako XML do syndykacji. Bez tworzenia pliku UTF-8 od samego początku (zmiana opcji w IDE i „Utwórz nowy plik”) lub dodawanie BOM na początku pliku
Nie byłem w stanie zapisać francuskich liter w pliku XML.
źródło
Jedną praktyczną różnicą jest to, że jeśli napiszesz skrypt powłoki dla Mac OS X i zapiszesz go jako zwykły UTF-8, otrzymasz odpowiedź:
w odpowiedzi na linię shebang określającą, której powłoki chcesz użyć:
Jeśli zapiszesz jako UTF-8, brak BOM (powiedzmy w BBEdit ) wszystko będzie dobrze.
źródło
Jak wspomniano powyżej, UTF-8 z BOM może powodować problemy z oprogramowaniem nieobsługującym BOM (lub zgodnym). Kiedyś edytowałem pliki HTML zakodowane jako UTF-8 + BOM w opartym na Mozilli KompoZer , ponieważ klient wymagał programu WYSIWYG .
Niezmiennie układ zostanie zniszczony podczas zapisywania. Zajęło mi trochę czasu, żeby się tym zająć. Pliki te następnie działały dobrze w Firefoksie, ale pokazały dziwactwo CSS w Internet Explorerze, niszcząc układ. Po wielu godzinach majstrowania przy połączonych plikach CSS okazało się, że Internet Explorer nie lubił pliku HTML BOMfed. Nigdy więcej.
Właśnie znalazłem to w Wikipedii:
źródło
FAQ Unicode Byte Order Mark (BOM) zawiera zwięzłą odpowiedź:
źródło
Od http://en.wikipedia.org/wiki/Byte-order_mark :
Zawsze użycie BOM w twoim pliku zapewni, że zawsze otworzy się poprawnie w edytorze obsługującym UTF-8 i BOM.
Mój prawdziwy problem z brakiem BOM jest następujący. Załóżmy, że mamy plik zawierający:
Bez BOM jest to otwierane jako ANSI w większości edytorów. Tak więc inny użytkownik tego pliku otwiera go i dodaje niektóre znaki rodzime, na przykład:
Ups ... Teraz plik jest nadal w ANSI i zgadnij co, „αβγ” nie zajmuje 6 bajtów, ale 3. To nie jest UTF-8, a to powoduje inne problemy w późniejszym etapie łańcucha rozwoju.
źródło
Oto moje doświadczenia z wnioskami ściągania Visual Studio, Sourcetree i Bitbucket, co sprawiało mi pewne problemy:
Okazuje się, że BOM z podpisem będzie zawierać znak czerwonej kropki na każdym pliku podczas przeglądania żądania ściągnięcia (może to być dość denerwujące).
Jeśli najedziesz na niego kursorem, wyświetli się znak taki jak „ufeff”, ale okazuje się, że Sourcetree nie wyświetla tego typu znaków bajtowych, więc najprawdopodobniej skończy się na twoich żądaniach ściągania, co powinno być ok, ponieważ tak właśnie Visual Studio 2017 koduje teraz nowe pliki, więc może Bitbucket powinien to zignorować lub pokazać w inny sposób, więcej informacji tutaj:
Znacznik czerwonej kropki widok różnic BitBucket
źródło
UTF z BOM jest lepszy, jeśli używasz UTF-8 w plikach HTML i jeśli używasz serbskiej cyrylicy, serbskiej łaciny, niemieckiej, węgierskiej lub jakiegoś egzotycznego języka na tej samej stronie.
Tak oceniam (30 lat branży komputerowej i informatycznej).
źródło