Qual è la differenza tra UTF-8 e UTF-8 senza BOM?


818

Cosa c'è di diverso tra UTF-8 e UTF-8 senza una distinta base ? Che è migliore?


77
UTF-8 può essere rilevato meglio dai contenuti che dalla distinta base. Il metodo è semplice: prova a leggere il file (o una stringa) come UTF-8 e se ciò ha esito positivo, supponi che i dati siano UTF-8. Altrimenti supponiamo che sia CP1252 (o qualche altra codifica a 8 bit). Qualsiasi codifica a 8 bit non UTF-8 conterrà quasi certamente sequenze non consentite da UTF-8. ASCII puro (7 bit) viene interpretato come UTF-8, ma anche il risultato è corretto.
Tronic,

39
La scansione di file di grandi dimensioni per il contenuto UTF-8 richiede tempo. Una DBA rende questo processo molto più veloce. In pratica spesso devi fare entrambe le cose. Il colpevole al giorno d'oggi è che ancora molto contenuto di testo non è Unicode, e mi imbatto ancora in strumenti che dicono che fanno Unicode (ad esempio UTF-8) ma emettono il loro contenuto in una tabella codici diversa.
Jeroen Wiert Pluimers il

10
@Tronic Non credo proprio che "meglio" si adatti a questo caso. Dipende dall'ambiente. Se si è certi che tutti i file UTF-8 siano contrassegnati con una DBA che controllare la DBA sia il modo "migliore" , perché è più veloce e più affidabile.
mg30rg

32
UTF-8 non ha una DBA. Quando si inserisce un punto di codice U + FEFF all'inizio di un file UTF-8, è necessario prestare particolare attenzione per gestirlo. Questa è solo una di quelle bugie sui nomi di Microsoft, come chiamare una codifica "Unicode" quando non esiste nulla del genere.
tchrist,

7
"Il mainframe moderno (e AIX) è little endian UTF-8 a conoscenza" UTF-8 non ha un endedness ! non c'è mescolamento di byte in giro per mettere coppie o gruppi di quattro nel giusto "ordine" per un particolare sistema! Per rilevare una sequenza di byte UTF-8, può essere utile notare che il primo byte di una sequenza multi-byte "codepoint" (i byte NON "normali" ASCII) ha il bit MS impostato e tutti altri 1-3 successivamente bit meno significativi seguiti da un bit di reset. Il numero totale di quei bit impostati è uno in meno di byte che si trovano in quel punto di codice e TUTTI avranno il set di MSB ...
SlySven

Risposte:


773

La BOM UTF-8 è una sequenza di byte all'inizio di un flusso di testo ( 0xEF, 0xBB, 0xBF) che consente al lettore di indovinare in modo più affidabile un file come codificato in UTF-8.

Normalmente, la distinta base viene utilizzata per segnalare l' endianità di una codifica, ma poiché l'endianità è irrilevante per UTF-8, la distinta base non è necessaria.

Secondo lo standard Unicode , la distinta base per i file UTF-8 non è consigliata :

2.6 Schemi di codifica

... L'uso di una DBA non è richiesto né raccomandato per UTF-8, ma può essere riscontrato in contesti in cui i dati UTF-8 vengono convertiti da altri moduli di codifica che utilizzano una DBA o in cui la DBA viene utilizzata come firma UTF-8 . Vedere la sottosezione "Contrassegno ordine byte" nella Sezione 16.8, Speciali , per ulteriori informazioni.


114
Potrebbe non essere raccomandato ma dalla mia esperienza nelle conversioni ebraiche la distinta base è talvolta cruciale per il riconoscimento UTF-8 in Excel e può fare la differenza tra Jibrish ed ebraico
Matanya,

26
Potrebbe non essere raccomandato ma ha fatto miracoli al mio script PowerShell quando ho provato a produrre "æøå"
Marius,

63
Indipendentemente dal fatto che non sia raccomandato dallo standard, è consentito e preferisco di gran lunga avere qualcosa da agire come una firma UTF-8 piuttosto che le alternative di assumere o indovinare. Il software conforme a Unicode dovrebbe / deve essere in grado di gestire la sua presenza, quindi incoraggio personalmente il suo utilizzo.
martineau,

30
@ bames53: Sì, in un mondo ideale che memorizza la codifica dei file di testo come metadati del file system sarebbe un modo migliore per preservarlo. Ma la maggior parte di noi che vive nel mondo reale non può cambiare il file system dei sistemi operativi su cui i nostri programmi vengono eseguiti, quindi l'utilizzo della firma BOM indipendente dalla piattaforma dello standard Unicode sembra il migliore e più pratico IMHO alternativo.
martineau,

34
@martineau Proprio ieri mi sono imbattuto in un file con una BOM UTF-8 che non era UTF-8 (era CP936). La cosa spiacevole è che i responsabili dell'immensa quantità di dolore causata dalla distinta base UTF-8 ne sono in gran parte ignari.
bames53

243

Le altre eccellenti risposte hanno già risposto che:

  • Non c'è alcuna differenza ufficiale tra UTF-8 e BOM-ed UTF-8
  • Una stringa UTF-8 della BOM inizierà con i tre byte seguenti. EF BB BF
  • Quei byte, se presenti, devono essere ignorati quando si estrae la stringa dal file / flusso.

Ma, come ulteriore informazione a questo proposito, la distinta base per UTF-8 potrebbe essere un buon modo per "annusare" se una stringa fosse codificata in UTF-8 ... O potrebbe essere una stringa legittima in qualsiasi altra codifica ...

Ad esempio, i dati [EF BB BF 41 42 43] potrebbero essere:

  • La stringa ISO-8859-1 legittima "ï» ¿ABC "
  • La stringa UTF-8 legittima "ABC"

Quindi, mentre può essere bello riconoscere la codifica di un contenuto di file osservando i primi byte, non dovresti fare affidamento su questo, come mostrato nell'esempio sopra

Le codifiche dovrebbero essere conosciute, non divinate.


60
@Alcott: hai capito bene. La stringa [EF BB BF 41 42 43] è solo un mucchio di byte. Hai bisogno di informazioni esterne per scegliere come interpretarle. Se ritieni che quei byte siano stati codificati usando ISO-8859-1, la stringa è "ï» ¿ABC ". Se ritieni che quei byte siano stati codificati usando UTF-8, allora è "ABC". Se non lo sai, allora devi provare a scoprirlo. La DBA potrebbe essere un indizio. L'assenza di caratteri non validi quando decodificati come UTF-8 potrebbe essere un altro ... Alla fine, a meno che non sia possibile memorizzare / trovare la codifica in qualche modo, un array di byte è solo un array di byte.
paercebal,

19
@paercebal Mentre "ï» ¿"è valido latino-1, è molto improbabile che un file di testo inizi con quella combinazione. Lo stesso vale per i marcatori ucs2-le / be ÿþ e þÿ. Inoltre non puoi mai sapere.
user877329,

16
@deceze Probabilmente non è linguisticamente valido: prima ï (che è ok), quindi alcune virgolette senza spazio in mezzo (non ok). ¿Indica che è spagnolo ma ï non è utilizzato in spagnolo. Conclusione: non è latino-1 con una certezza ben al di sopra della certezza senza di essa.
user877329

20
@utente Certo, non ha necessariamente senso. Ma se il tuo sistema si basa sull'ipotesi , ecco dove arrivano le incertezze. Alcuni utenti malintenzionati inviano il testo a partire da queste 3 lettere di proposito, e il tuo sistema improvvisamente assume che sta guardando UTF-8 con una DBA, tratta il testo come UTF-8 dove dovrebbe usare Latin-1 e ha luogo un'iniezione Unicode. Solo un esempio ipotetico, ma certamente possibile. Non puoi giudicare una codifica di testo in base al suo contenuto, punto.
Inganno

40
"Le codifiche dovrebbero essere conosciute, non divinate." Il cuore e l'anima del problema. +1, buon signore. In altre parole: standardizzare i tuoi contenuti e dire "Usiamo sempre questa codifica. Periodo. Scrivila in quel modo. Leggi in quel modo" o sviluppa un formato esteso che consenta di archiviare la codifica come metadati. (Quest'ultimo probabilmente ha bisogno di un po 'di "codifica standard bootstrap". Come dire "La parte che ti dice la codifica è sempre ASCII.")
jpmc26

135

Esistono almeno tre problemi con l'inserimento di una distinta base nei file codificati UTF-8.

  1. I file che non contengono testo non sono più vuoti perché contengono sempre la DBA.
  2. I file che contengono testo che si trova all'interno del sottoinsieme ASCII di UTF-8 non sono più essi stessi ASCII perché la BOM non è ASCII, il che rende alcuni strumenti esistenti rotti e può essere impossibile per gli utenti sostituire tali strumenti legacy.
  3. Non è possibile concatenare più file insieme perché ogni file ora ha una DBA all'inizio.

E, come altri hanno già detto, non è né sufficiente né necessario disporre di una DBA per rilevare che qualcosa è UTF-8:

  • Non è sufficiente perché può accadere che una sequenza di byte arbitraria inizi con la sequenza esatta che costituisce la distinta base.
  • Non è necessario perché puoi semplicemente leggere i byte come se fossero UTF-8; se ciò ha esito positivo, è, per definizione, valido UTF-8.

8
Per quanto riguarda il punto 1 "I file che non contengono testo non sono più vuoti perché contengono sempre la DBA", questo (1) unisce il livello del filesystem del sistema operativo con il livello del contenuto interpretato, inoltre (2) presuppone erroneamente che usando la DBA si debba mettere un DBA anche in ogni file altrimenti vuoto. La soluzione pratica a (1) è di non farlo (2). In sostanza, il reclamo si riduce a "è possibile inserire in modo non pratico una distinta base in un file altrimenti vuoto, impedendo così il rilevamento più semplice di file logicamente vuoti (controllando le dimensioni del file)". Un buon software dovrebbe essere in grado di gestirlo, poiché ha uno scopo.
Saluti e hth. - Alf,

7
Per quanto riguarda il punto 2, "I file che contengono testo ASCII non sono più essi stessi ASCII", questo combina ASCII con UTF-8. Un file UTF-8 che contiene testo ASCII non è ASCII, è UTF-8. Allo stesso modo, un file UTF-16 che contiene testo ASCII non è ASCII, è UTF-16. E così via. ASCII è un codice a byte singolo a 7 bit. UTF-8 è un'estensione a lunghezza variabile di 8 bit di ASCII. Se "strumenti si rompono" a causa di> 127 valori, non sono adatti per un mondo a 8 bit. Una semplice soluzione pratica è quella di utilizzare solo file ASCII con strumenti che si suddividono per valori di byte non ASCII. Una soluzione probabilmente migliore è quella di abbandonare quegli strumenti non buoni.
Saluti e hth. - Alf,

8
Per quanto riguarda il punto 3, "Non è possibile concatenare più file insieme perché ogni file ora ha una DBA all'inizio" è semplicemente sbagliato. Non ho problemi a concatenare i file UTF-8 con BOM, quindi è chiaramente possibile. Penso che forse intendevi dire che Unix-land catnon ti darà un risultato pulito , un risultato che ha una DBA solo all'inizio. Se intendevi questo, allora è perché catfunziona a livello di byte, non a livello di contenuti interpretati, e in modo simile catnon può gestire le fotografie, diciamo. Tuttavia non fa molto male. Questo perché la distinta componenti codifica uno spazio senza interruzioni di larghezza zero.
Saluti e hth. - Alf,

20
@ Cheersandhth.-Alf Questa risposta è corretta. Stai semplicemente sottolineando i bug di Microsoft.
tchrist,

9
@brighty: la situazione non è migliorata aggiungendo però un bom.
Deduplicatore,

84

Ecco alcuni esempi dell'utilizzo della distinta componenti che in realtà causa problemi reali e tuttavia molte persone non lo sanno.

La distinta componenti rompe gli script

Script shell, script Perl, script Python, script Ruby, script Node.js o qualsiasi altro eseguibile che deve essere eseguito da un interprete - tutto inizia con una riga shebang che assomiglia a una di quelle:

#!/bin/sh
#!/usr/bin/python
#!/usr/local/bin/perl
#!/usr/bin/env node

Indica al sistema quale interprete deve essere eseguito quando si richiama un tale script. Se lo script è codificato in UTF-8, si potrebbe essere tentati di includere una DBA all'inizio. Ma in realtà il "#!" i personaggi non sono solo personaggi. Sono in realtà un numero magico che sembra essere composto da due caratteri ASCII. Se metti qualcosa (come una DBA) prima di quei personaggi, allora il file sembrerà avere un numero magico diverso e questo può portare a problemi.

Vedi Wikipedia, articolo: Shebang, sezione: Numero magico :

I caratteri shebang sono rappresentati dagli stessi due byte nelle codifiche ASCII estese, incluso UTF-8, che viene comunemente utilizzato per gli script e altri file di testo sugli attuali sistemi simili a Unix. Tuttavia, i file UTF-8 possono iniziare con il segno di ordine dei byte (BOM) opzionale; se la funzione "exec" rileva specificamente i byte 0x23 e 0x21, la presenza della distinta base (0xEF 0xBB 0xBF) prima che lo shebang impedisca l'esecuzione dell'interprete di script.Alcune autorità sconsigliano di usare il segno dell'ordine dei byte negli script POSIX (tipo Unix), [14] per questo motivo e per una più ampia interoperabilità e preoccupazioni filosofiche. Inoltre, in UTF-8 non è necessario un contrassegno dell'ordine dei byte, poiché tale codifica non presenta problemi di endianness; serve solo per identificare la codifica come UTF-8. [enfasi aggiunta]

La distinta base è illegale in JSON

Vedi RFC 7159, Sezione 8.1 :

Le implementazioni NON DEVONO aggiungere un segno di ordine byte all'inizio di un testo JSON.

La distinta componenti è ridondante in JSON

Non solo è illegale in JSON, ma non è nemmeno necessario determinare la codifica dei caratteri perché ci sono modi più affidabili per determinare in modo inequivocabile sia la codifica dei caratteri che l'endianità utilizzati in qualsiasi flusso JSON (vedere questa risposta per i dettagli).

BOM rompe i parser JSON

Non solo è illegale in JSON e non è necessario , in realtà rompe tutto il software che determina la codifica utilizzando il metodo presentato in RFC 4627 :

Determinazione della codifica e dell'endianità di JSON, esaminando i primi quattro byte per il byte 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

Ora, se il file inizia con BOM sarà simile al seguente:

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

Nota che:

  1. UTF-32BE non inizia con tre NUL, quindi non verrà riconosciuto
  2. UTF-32LE il primo byte non è seguito da tre NUL, quindi non verrà riconosciuto
  3. UTF-16BE ha un solo NUL nei primi quattro byte, quindi non verrà riconosciuto
  4. UTF-16LE ha un solo NUL nei primi quattro byte, quindi non verrà riconosciuto

A seconda dell'implementazione, tutti questi possono essere interpretati in modo errato come UTF-8 e quindi interpretati erroneamente o respinti come UTF-8 non validi, o non riconosciuti affatto.

Inoltre, se l'implementazione verifica JSON valido come raccomandato, rifiuterà anche l'input effettivamente codificato come UTF-8, perché non inizia con un carattere ASCII <128 come dovrebbe secondo RFC.

Altri formati di dati

La distinta base in JSON non è necessaria, è illegale e rompe il software che funziona correttamente secondo la RFC. Dovrebbe essere un nobrainer non usarlo e poi, ci sono sempre persone che insistono nel rompere JSON usando DBA, commenti, regole di quotazione diverse o tipi di dati diversi. Ovviamente chiunque è libero di usare cose come le distinte base o qualsiasi altra cosa se ne hai bisogno, quindi non chiamarlo JSON.

Per formati di dati diversi da JSON, dai un'occhiata a come appare davvero. Se le uniche codifiche sono UTF- * e il primo carattere deve essere un carattere ASCII inferiore a 128, allora hai già tutte le informazioni necessarie per determinare sia la codifica che l'endianità dei tuoi dati. L'aggiunta di distinte componenti anche come funzionalità opzionale renderebbe solo più complicato e soggetto a errori.

Altri usi della distinta base

Per quanto riguarda gli usi al di fuori di JSON o degli script, penso che ci siano già ottime risposte qui. Volevo aggiungere informazioni più dettagliate in particolare su script e serializzazione, perché è un esempio di caratteri DBA che causano problemi reali.


5
rfc7159 che sostituisce rfc4627 suggerisce in realtà che sostenere la DBA potrebbe non essere così malvagio. Fondamentalmente non avere una DBA è solo un problema ambiguo, quindi i vecchi software Windows e Unix che non sono in grado di riconoscere Unicode possono ancora elaborare utf-8.
Eric Grange,

2
Sembra che JSON debba essere aggiornato per supportarlo, lo stesso con gli script Perl, gli script Python, gli script Ruby, Node.js. Solo perché queste piattaforme hanno scelto di non includere il supporto, non necessariamente si annulla l'utilizzo di BOM. Apple ha cercato di uccidere Adobe per alcuni anni e Adobe è ancora in circolazione. Ma un post illuminante.
htm11h

13
@EricGrange, sembri supportare fortemente la distinta base, ma non ti rendi conto che questo renderebbe il formato onnipresente, universalmente utile, minimo "testo normale" una reliquia del passato pre-UTF8! L'aggiunta di qualsiasi tipo di intestazione (in banda) al flusso di testo normale imporrebbe, per definizione, un protocollo obbligatorio ai file di testo più semplici, rendendolo mai più "semplice"! E per quale guadagno? Per supportare tutti gli altri , antichi codifiche CP che anche non hanno avuto le firme, per cui si potrebbe loro errore con UTF-8? (A proposito, ASCII è anche UTF-8. Quindi, una DBA anche per quelli?;) Dai.)
Sz.

2
Questa risposta è il motivo per cui sono arrivato a questa domanda! Creo i miei script bash in Windows e riscontro molti problemi durante la pubblicazione di tali script su Linux! Stessa cosa con i file jason.
Tono Nam,

2
Vorrei poter votare questa risposta una cinquantina di volte. Voglio anche aggiungere che a questo punto UTF-8 ha vinto la guerra degli standard e quasi tutto il testo prodotto su Internet è UTF-8. Alcuni dei linguaggi di programmazione più popolari (come C # e Java) usano UTF-16 internamente, ma quando i programmatori che usano quei linguaggi scrivono file per produrre flussi, li codificano quasi sempre come UTF-8. Pertanto, non ha più senso avere una DBA per contrassegnare un file UTF-8; UTF-8 dovrebbe essere l'impostazione predefinita da utilizzare durante la lettura e provare altre codifiche solo se la decodifica UTF-8 non riesce.
rmunn,

51

Cosa c'è di diverso tra UTF-8 e UTF-8 senza BOM?

Risposta breve: in UTF-8, una DBA è codificata come byte EF BB BFall'inizio del file.

Risposta lunga:

Inizialmente, si prevedeva che Unicode fosse codificato in UTF-16 / UCS-2. La distinta componenti è stata progettata per questo modulo di codifica. Quando si hanno unità di codice a 2 byte, è necessario indicare in quale ordine si trovano quei due byte e una convenzione comune per farlo è quella di includere il carattere U + FEFF come "Segno di ordine di byte" all'inizio dei dati. Il carattere U + FFFE è permanentemente non assegnato in modo che la sua presenza possa essere utilizzata per rilevare l'ordine di byte errato.

UTF-8 ha lo stesso ordine di byte indipendentemente dall'endianness della piattaforma, quindi non è necessario un contrassegno di ordine di byte. Tuttavia, può verificarsi (come sequenza di byte EF BB FF) nei dati convertiti in UTF-8 da UTF-16 o come "firma" per indicare che i dati sono UTF-8.

Che è migliore?

Senza. Come ha risposto Martin Cote, lo standard Unicode non lo raccomanda. Causa problemi con software non compatibile con la distinta componenti.

Un modo migliore per rilevare se un file è UTF-8 consiste nell'eseguire un controllo di validità. UTF-8 ha regole rigide su quali sequenze di byte sono valide, quindi la probabilità di un falso positivo è trascurabile. Se una sequenza di byte sembra UTF-8, probabilmente lo è.


8
ciò invaliderebbe anche UTF-8 valido con un singolo byte errato, sebbene: /
endolith

8
-1 re "Causa problemi con software non compatibile con BOM.", Non è mai stato un problema per me, ma al contrario, l'assenza di BOM causa problemi con il software compatibile con BOM (in particolare Visual C ++) è stato un problema. Quindi questa affermazione è molto specifica per la piattaforma , un punto di vista stretto sulla terra di Unix, ma è presentata in modo fuorviante come se si applica in generale. Che non lo fa.
Saluti e hth. - Alf,

6
No, UTF-8 non ha distinta base. Questa risposta non è corretta Vedi lo standard Unicode.
tchrist,

2
Puoi persino pensare di avere un file ASCII puro quando guardi solo i byte. Ma questo potrebbe essere anche un file utf-16 in cui dovresti guardare le parole e non i byte. I software moderni dovrebbero essere consapevoli delle distinte base. Continuare a leggere utf-8 può fallire se si rilevano sequenze non valide, punti di codice che possono usare una sequenza più piccola o punti di codice che sono surrogati. Per la lettura utf-16 potrebbe anche fallire quando ci sono surrogati orfani.
luminoso

1
@Alf, non sono d'accordo con la tua interpretazione di un atteggiamento non-BOM come " specifico per la piattaforma , un punto di vista stretto sulla terra Unix". Per me, l'unico modo in cui la mentalità ristretta poteva risiedere in "Unix land" era se MS e Visual C ++ venissero prima di * NIX, cosa che non è accaduta. Il fatto che MS (presumo consapevolmente) ha iniziato a utilizzare una distinta in UTF-8 piuttosto che UTF-16 mi suggerisce che hanno promosso la rottura sh, perl, g++e molti altri liberi e potenti strumenti. Vuoi che le cose funzionino? Basta acquistare le versioni di MS. MS ha creato il problema specifico della piattaforma, proprio come il disastro della loro gamma \ x80- \ x95.
bballdave025,

30

UTF-8 con distinta base viene identificato meglio. Ho raggiunto questa conclusione nel modo più duro. Sto lavorando a un progetto in cui uno dei risultati è un file CSV , inclusi i caratteri Unicode.

Se il file CSV viene salvato senza DBA, Excel pensa che sia ANSI e mostra incomprensibili. Dopo aver aggiunto "EF BB BF" nella parte anteriore (ad esempio, salvandolo nuovamente utilizzando Blocco note con UTF-8; o Notepad ++ con UTF-8 con BOM), Excel lo apre correttamente.

La preparazione del carattere DBA ai file di testo Unicode è consigliata da RFC 3629: "UTF-8, un formato di trasformazione di ISO 10646", novembre 2003 all'indirizzo http://tools.ietf.org/html/rfc3629 (queste ultime informazioni sono disponibili su: http://www.herongyang.com/Unicode/Notepad-Byte-Order-Mark-BOM-FEFF-EFBBBF.html )


6
Grazie per questo eccellente consiglio nel caso in cui si stiano creando file UTF-8 per l'uso da parte di Excel. In altre circostanze, seguirei comunque le altre risposte e salterei la DBA.
Barfuin,

5
È anche utile se crei file che contengono solo ASCII e in seguito potrebbero essere stati aggiunti non ascii. Ho appena incontrato un problema del genere: il software che prevede utf8, crea file con alcuni dati per l'editing dell'utente. Se il file iniziale contiene solo ASCII, viene aperto in alcuni editor e quindi salvato, finisce in latino-1 e tutto si rompe. Se aggiungo la distinta base, verrà rilevata come UTF8 dall'editor e tutto funzionerà.
Roberto Alsina,

1
Ho trovato più strumenti correlati alla programmazione che richiedono alla distinta componenti di riconoscere correttamente i file UTF-8. Visual Studio, SSMS, SoureTree ....
kjbartel,

5
Dove leggi una raccomandazione per l'utilizzo di una DBA in tale RFC? Al massimo, vi è una forte raccomandazione di non vietarlo in determinate circostanze in cui è difficile farlo.
Deduplicatore l'

8
Excel pensa che sia ANSI e mostra incomprensibili quindi il problema è in Excel.
Isaac,

17

La BOM tende ad espandersi (nessun gioco di parole previsto (sic)) da qualche parte, da qualche parte. E quando esplode (ad esempio, non viene riconosciuto da browser, editor, ecc.), Viene visualizzato come i caratteri strani all'inizio del documento (ad esempio, file HTML, risposta JSON , RSS , ecc.) e provoca il tipo di imbarazzi come il recente problema di codifica riscontrato durante il discorso di Obama su Twitter .

È molto fastidioso quando si presenta in punti difficili da eseguire il debug o quando i test vengono trascurati. Quindi è meglio evitarlo a meno che tu non debba usarlo.


Sì, ho passato ore a identificare un problema causato dalla codifica di un file come UTF-8 anziché UTF-8 senza distinta base. (Il problema si presentava solo in IE7, il che mi ha portato a un inseguimento d'oca. Ho usato "include" di Django.)
user984003

Lettori futuri: Nota che il problema del tweet che ho menzionato sopra non era strettamente correlato alla distinta base, ma se lo fosse, il tweet sarebbe confuso in un modo simile, ma all'inizio del tweet.
Halil Özgür,

12
@ user984003 No, il problema è che Microsoft ti ha fuorviato. Quello che chiama UTF-8 non è UTF-8. Ciò che chiama UTF-8 senza BOM è ciò che realmente è UTF-8.
tchrist,

cosa aggiunge il "sic" al tuo "no pun pun"
JoelFan,

2
@JoelFan Non riesco più a ricordare ma immagino che il gioco di parole potrebbe essere stato inteso nonostante le affermazioni dell'autore :)
Halil Özgür,

17

Domanda: Cosa c'è di diverso tra UTF-8 e UTF-8 senza una distinta base? Che è migliore?

Ecco alcuni estratti dall'articolo di Wikipedia sul segno di ordine dei byte (BOM) che credo offrono una solida risposta a questa domanda.

Sul significato di BOM e UTF-8:

Lo standard Unicode consente la distinta base in UTF-8 , ma non ne richiede né raccomanda l'utilizzo. L'ordine dei byte non ha alcun significato in UTF-8, quindi il suo solo utilizzo in UTF-8 è di segnalare all'inizio che il flusso di testo è codificato in UTF-8.

Argomento per NON utilizzare una DBA:

La motivazione principale per non usare una DBA è la retrocompatibilità con software che non è compatibile con Unicode ... Un'altra motivazione per non usare una DBA è di incoraggiare UTF-8 come codifica "predefinita".

Argomento PER l' utilizzo di una DBA:

L'argomento per l'utilizzo di una distinta componenti è che senza di essa è necessaria l'analisi euristica per determinare quale carattere sta codificando un file. Storicamente tale analisi, per distinguere varie codifiche a 8 bit, è complicata, soggetta a errori e talvolta lenta. Sono disponibili numerose librerie per facilitare l'attività, come Mozilla Universal Charset Detector e International Components for Unicode.

I programmatori presumono erroneamente che il rilevamento di UTF-8 sia ugualmente difficile (non a causa della stragrande maggioranza delle sequenze di byte non sono UTF-8 non valide, mentre le codifiche che queste librerie stanno cercando di distinguere consentono tutte le possibili sequenze di byte). Pertanto non tutti i programmi compatibili con Unicode eseguono tale analisi e si affidano invece alla DBA.

In particolare, i compilatori e gli interpreti Microsoft e molti software su Microsoft Windows come Blocco note non leggeranno correttamente il testo UTF-8 a meno che non abbia solo caratteri ASCII o inizi con la DBA e aggiungeranno una DBA all'avvio quando si salva testo come UTF-8. Google Documenti aggiungerà una DBA quando un documento di Microsoft Word viene scaricato come file di testo semplice.

Su quale è meglio, CON o SENZA la DBA:

L' IETF raccomanda che se un protocollo (a) utilizza sempre UTF-8 o (b) ha un altro modo per indicare quale codifica viene utilizzata, allora "DOVREBBE vietare l'uso di U + FEFF come firma".

La mia conclusione:

Utilizzare la distinta componenti solo se la compatibilità con un'applicazione software è assolutamente essenziale.

Si noti inoltre che mentre l'articolo di Wikipedia indicato indica che molte applicazioni Microsoft fanno affidamento sulla distinta componenti per rilevare correttamente UTF-8, questo non è il caso di tutte le applicazioni Microsoft. Ad esempio, come sottolineato da @barlop , quando si utilizza il Prompt dei comandi di Windows con UTF-8 , i comandi sono tali typee morenon si prevede che la distinta componenti sia presente. Se la distinta componenti è presente, può essere problematica come per altre applicazioni.


† Il chcpcomando offre supporto per UTF-8 ( senza DBA) tramite la tabella codici 65001 .


5
Farei meglio a SENZA la DBA . Ho trovato che .htaccesse gzip compressionin combinazione con UTF-8 BOM dà un errore di codifica Variazione di codifica in UTF-8 senza BOM seguito ad un suggerimento come spiegato qui risolvere i problemi
Chetabahana

1
"Un'altra motivazione per non utilizzare una DBA è quella di incoraggiare UTF-8 come codifica" predefinita "." - Che è un argomento così forte e valido, che avresti potuto effettivamente fermare la risposta lì! ...; -o A meno che tu non abbia un'idea migliore per la rappresentazione universale del testo, cioè. ;) (Non so quanti anni hai, quanti anni hai dovuto soffrire nell'era pre-UTF8 (quando i linguisti consideravano disperatamente di cambiare anche i loro alfabeti), ma posso dirti che ogni secondo ci avviciniamo alla liberazione il caos di tutte le antiche codifiche a byte singolo senza metadati, invece di avere "l'uno" è pura gioia.)
Sz.

Vedi anche questo commento su come aggiungere una DBA (o qualcosa del genere!) Al più semplice dei formati di file di testo, "testo semplice", significherebbe impedire che il miglior formato di codifica del testo universale sia "semplice" e "semplice" (es. "overheadless")! ...
Sz.

La BOM è principalmente problematica su Linux perché molte utility non supportano davvero Unicode (per esempio, tronceranno felicemente nel mezzo di punti di codice). Per la maggior parte degli altri ambienti software moderni, utilizzare la distinta componenti ogni volta che la codifica non è inequivocabile (tramite specifiche o metadati).
Eric Grange,

9

Questa domanda ha già un milione di risposte e molte di esse sono abbastanza buone, ma volevo provare a chiarire quando una distinta base dovrebbe o non dovrebbe essere utilizzata.

Come accennato, qualsiasi uso della DBA UTF (Byte Order Mark) per determinare se una stringa è UTF-8 o meno è congetture istruite. Se sono disponibili metadati adeguati (come charset="utf-8"), allora sai già cosa dovresti utilizzare, ma per il resto dovrai testare e fare alcune ipotesi. Ciò comporta la verifica se il file da cui proviene una stringa inizia con il codice byte esadecimale, EF BB BF.

Se viene trovato un codice byte corrispondente alla DBA UTF-8, la probabilità è abbastanza elevata da presupporre che sia UTF-8 e si può andare da lì. Se costretto a fare questa ipotesi, tuttavia, un ulteriore controllo degli errori durante la lettura sarebbe comunque una buona idea nel caso in cui qualcosa si confonda. Dovresti supporre che una distinta base non sia UTF-8 (cioè latino-1 o ANSI) se l'ingresso sicuramente non dovrebbe essere UTF-8 in base alla sua sorgente. Se non vi è alcuna distinta base, tuttavia, è possibile determinare semplicemente se si suppone che sia UTF-8 convalidando rispetto alla codifica.

Perché una DBA non è consigliata?

  1. Il software non compatibile con Unicode o scarsamente conforme può presumere che sia latino-1 o ANSI e non elimini la distinta componenti dalla stringa, il che può ovviamente causare problemi.
  2. Non è davvero necessario (basta verificare se i contenuti sono conformi e utilizzare sempre UTF-8 come fallback quando non è possibile trovare una codifica conforme)

Quando dovresti codificare con una DBA?

Se non sei in grado di registrare i metadati in altro modo (tramite un tag charset o un meta file system) e i programmi utilizzati come distinte componenti, devi codificare con una distinta componenti. Ciò è particolarmente vero su Windows in cui si presume che qualsiasi cosa senza BOM utilizzi una tabella codici legacy. La DBA dice a programmi come Office che, sì, il testo in questo file è Unicode; ecco la codifica utilizzata.

Quando si tratta di esso, gli unici file con cui abbia mai avuto problemi sono CSV. A seconda del programma, deve o non deve avere una DBA. Ad esempio, se si utilizza Excel 2007+ su Windows, è necessario codificarlo con una distinta componenti se si desidera aprirlo senza problemi e non è necessario ricorrere all'importazione dei dati.


2
L'ultima sezione della tua risposta è corretta al 100%: l' unica ragione per usare una DBA è quando devi interagire con un software difettoso che non usa UTF-8 come impostazione predefinita per analizzare i file sconosciuti.
rmunn,

8

Va notato che per alcuni file non è necessario disporre della DBA anche su Windows. Esempi sono SQL*pluso VBScriptfile. Nel caso in cui tali file contengano una distinta componenti, viene visualizzato un errore quando si tenta di eseguirli.


8

UTF-8 con BOM aiuta solo se il file contiene effettivamente alcuni caratteri non ASCII. Se è incluso e non ce ne sono, probabilmente romperà le applicazioni più vecchie che altrimenti avrebbero interpretato il file come semplice ASCII. Queste applicazioni falliranno sicuramente quando si imbatteranno in un carattere non ASCII, quindi secondo me la distinta base dovrebbe essere aggiunta solo quando il file può, e non dovrebbe essere più interpretato come semplice ASCII.

Voglio chiarire che preferisco non avere affatto la DBA. Aggiungilo se qualche vecchia immondizia si rompe senza di essa e non è possibile sostituire l'applicazione legacy.

Non farti aspettare una DBA per UTF-8.


7

Citato in fondo alla pagina di Wikipedia su BOM: http://en.wikipedia.org/wiki/Byte-order_mark#cite_note-2

"L'uso di una DBA non è richiesto né raccomandato per UTF-8, ma può essere riscontrato in contesti in cui i dati UTF-8 vengono convertiti da altri moduli di codifica che utilizzano una DBA o in cui la DBA viene utilizzata come firma UTF-8"


2
Hai qualche esempio in cui il software decide se utilizzare UTF-8 con / senza DBA, in base al fatto che la codifica precedente da cui sta codificando abbia o meno una DBA ?! Sembra un'affermazione assurda
barlop

7

UTF-8 senza BOM non ha alcuna BOM, il che non lo rende migliore di UTF-8 con BOM, tranne quando il consumatore del file deve sapere (o trarrebbe vantaggio dal sapere) se il file è codificato UTF-8 o no.

La distinta base è di solito utile per determinare l'endianità della codifica, che non è richiesta per la maggior parte dei casi d'uso.

Inoltre, la distinta componenti può essere un rumore / dolore non necessario per quei consumatori che non ne sono a conoscenza o che si preoccupano e può causare confusione all'utente.


2
"che non ha alcuna utilità per UTF-8 in quanto è comunque di 8 bit per glifo." Ehm ... no, solo glifi ASCII-7 sono 8 bit in UTF-8. Qualunque cosa oltre a ciò sarà 16, 24 o 32 bit.
Powerlord,

3
"La distinta base è di solito utile per determinare l'endianità della codifica, che non è richiesta per la maggior parte dei casi d'uso." ... l'endianness semplicemente non si applica a UTF-8, indipendentemente dal caso d'uso
JoelFan,

6

Lo guardo da una prospettiva diversa. Penso che UTF-8 con BOM sia migliore in quanto fornisce ulteriori informazioni sul file. Uso UTF-8 senza DBA solo se ho problemi.

Sto usando più lingue (anche cirillico ) sulle mie pagine per molto tempo e quando i file vengono salvati senza distinta base e li riapro per la modifica con un editor (come cherouvim anche ha notato), alcuni personaggi sono corrotti.

Notare che il classico Blocco note di Windows salva automaticamente i file con una DBA quando si tenta di salvare un file appena creato con codifica UTF-8.

Salvo personalmente i file di scripting lato server (.asp, .ini, .aspx) con i file BOM e .html senza BOM .


4
Grazie per l'eccellente suggerimento sul classico Blocco note di Windows. Ho già trascorso un po 'di tempo a scoprire la stessa identica cosa. La mia conseguenza fu di usare sempre Notepad ++ invece del classico Blocco note di Windows. :-)
barfuin

È meglio che usi Madedit. È l'unico editor che - in modalità esadecimale - mostra un carattere se selezioni una sequenza utf-8 byte anziché una base 1: 1 tra byte e carattere. Un editor esadecimale che è a conoscenza di un file UTF-8 dovrebbe eseguire il bevave come fa Madedit!
luminoso

@brighty Non penso che tu abbia bisogno di uno a uno per il bene della DBA. non importa, non ci vuole molto a riconoscere che una distinta base utf-8 è efbbbf o fffe (di fffe se letto male). Si può semplicemente eliminare quei byte. Non è male però avere una mappatura per il resto del file, ma anche essere in grado di eliminare byte per byte anche
barlop

@barlop Perché dovresti voler eliminare una DBA utf-8 se il contenuto del file è codificato in utf-8? La distinta base è riconosciuta dai moderni visualizzatori di testo, controlli di testo e editor di testo. Una vista uno a uno di una sequenza utf-8 non ha senso, poiché n byte danno come risultato un carattere. Naturalmente un editor di testo o un editor esadecimale dovrebbe consentire di eliminare qualsiasi byte, ma ciò può portare a sequenze utf-8 non valide.
luminoso

@brighty utf-8 con bom è una codifica e utf-8 senza bom è una codifica. Il prompt cmd usa utf8 senza bom .. quindi se hai un file utf8, esegui il comando chcp 65001per il supporto utf8, è utf8 senza bom. Se lo fai type myfile, verrà visualizzato correttamente solo se non c'è nessuna distorsione. Se lo fai echo aaa>a.ao echo אאא>a.a per generare i caratteri nel file aa, e hai chcp 65001, verrà emesso senza DBA.
barlop

6

Quando si desidera visualizzare informazioni codificate in UTF-8, è possibile che non si verifichino problemi. Dichiara ad esempio un documento HTML come UTF-8 e avrai tutto ciò che viene visualizzato nel tuo browser contenuto nel corpo del documento.

Ma non è così quando abbiamo file di testo, CSV e XML, sia su Windows che su Linux.

Ad esempio, un file di testo in Windows o Linux, una delle cose più semplici che si possano immaginare, non è (di solito) UTF-8.

Salvalo come XML e dichiaralo come UTF-8:

<?xml version="1.0" encoding="UTF-8"?>

Non verrà visualizzato (non verrà letto) correttamente, anche se è dichiarato come UTF-8.

Avevo una serie di dati contenenti lettere francesi, che dovevano essere salvati come XML per syndication. Senza creare un file UTF-8 fin dall'inizio (modificando le opzioni in IDE e "Crea nuovo file") o aggiungendo la DBA all'inizio del file

$file="\xEF\xBB\xBF".$string;

Non sono stato in grado di salvare le lettere francesi in un file XML.


1
FTM, in XML, penso che dovresti mantenere il file come ASCII e utilizzare invece le entità .
Alois Mahdal,

4
So che questa è una vecchia risposta, ma voglio solo menzionare che è sbagliato. File di testo su Linux (non posso parlare per altri Unix) di solito / sono / UTF-8.
Functino,

6

Una differenza pratica è che se scrivi uno script di shell per Mac OS X e lo salvi come semplice UTF-8, otterrai la risposta:

#!/bin/bash: No such file or directory

in risposta alla linea shebang specificando quale shell si desidera utilizzare:

#!/bin/bash

Se salvi come UTF-8, nessuna DBA (diciamo in BBEdit ) andrà tutto bene.


8
Questo perché Microsoft ha scambiato il significato di ciò che dice lo standard. UTF-8 non ha una DBA: hanno creato Microsoft UTF-8 che inserisce una DBA spuria davanti al flusso di dati e poi ti ha detto che no, in realtà è UTF-8. Non è. Si sta semplicemente estendendo e corrompendo.
tchrist,

4

Come accennato in precedenza, UTF-8 con BOM può causare problemi con software non compatibile con BOM (o compatibile). Una volta ho modificato i file HTML codificati come UTF-8 + BOM con KompoZer basato su Mozilla , poiché un client richiedeva quel programma WYSIWYG .

Invariabilmente il layout verrebbe distrutto durante il salvataggio. Mi ci è voluto del tempo per smanettare. Questi file hanno funzionato bene in Firefox, ma hanno mostrato una stranezza CSS in Internet Explorer che ha distrutto nuovamente il layout. Dopo aver armeggiato per ore inutilmente con i file CSS collegati, ho scoperto che a Internet Explorer non piaceva il file HTML BOMfed. Mai più.

Inoltre, ho appena trovato questo in Wikipedia:

I caratteri shebang sono rappresentati dagli stessi due byte nelle codifiche ASCII estese, incluso UTF-8, che viene comunemente utilizzato per gli script e altri file di testo sugli attuali sistemi simili a Unix. Tuttavia, i file UTF-8 possono iniziare con il segno di ordine dei byte (BOM) opzionale; se la funzione "exec" rileva specificamente i byte 0x23 0x21, allora la presenza della distinta base (0xEF 0xBB 0xBF) prima che lo shebang impedisca l'esecuzione dell'interprete di script. Alcune autorità sconsigliano di usare il segno dell'ordine dei byte negli script POSIX (tipo Unix), [15] per questo motivo e per una più ampia interoperabilità e preoccupazioni filosofiche


4

Le domande frequenti su Unicode Byte Order Mark (BOM) forniscono una risposta concisa:

D: Come dovrei gestire le distinte base?

A: Ecco alcune linee guida da seguire:

  1. Un protocollo particolare (ad esempio convenzioni Microsoft per i file .txt) potrebbe richiedere l'uso della distinta base su determinati flussi di dati Unicode, come i file. Quando è necessario conformarsi a tale protocollo, utilizzare una DBA.

  2. Alcuni protocolli consentono distinte componenti opzionali nel caso di testo senza tag. In questi casi,

    • Laddove un flusso di dati di testo è noto come testo semplice, ma con codifica sconosciuta, la distinta componenti può essere utilizzata come firma. Se non è presente alcuna DBA, la codifica potrebbe essere qualsiasi cosa.

    • Laddove un flusso di dati di testo è noto per essere un semplice testo Unicode (ma non quale endiano), la distinta componenti può essere utilizzata come firma. Se non vi è alcuna distinta base, il testo deve essere interpretato come big-endian.

  3. Alcuni protocolli orientati al byte prevedono caratteri ASCII all'inizio di un file. Se UTF-8 viene utilizzato con questi protocolli, è necessario evitare l'uso della distinta base come firma del modulo di codifica.

  4. Laddove è noto il tipo preciso del flusso di dati (ad esempio Unicode big-endian o Unicode little-endian), la distinta base non deve essere utilizzata. In particolare, ogni volta che un flusso di dati viene dichiarato UTF-16BE, UTF-16LE, UTF-32BE o UTF-32LE non è necessario utilizzare una distinta base.


1

Da http://en.wikipedia.org/wiki/Byte-order_mark :

Il segno di ordine dei byte (BOM) è un carattere Unicode utilizzato per segnalare l'endianness (ordine dei byte) di un file di testo o flusso. Il suo punto di codice è U + FEFF. L'uso della DBA è facoltativo e, se utilizzato, dovrebbe apparire all'inizio del flusso di testo. Oltre al suo uso specifico come indicatore dell'ordine dei byte, il carattere DBA può anche indicare in quale delle diverse rappresentazioni Unicode è codificato il testo.

L'uso sempre di una DBA nel file assicurerà che si apra sempre correttamente in un editor che supporti UTF-8 e DBA.

Il mio vero problema con l'assenza di DBA è il seguente. Supponiamo di avere un file che contiene:

abc

Senza DBA questo si apre come ANSI nella maggior parte degli editor. Quindi un altro utente di questo file lo apre e aggiunge alcuni caratteri nativi, ad esempio:

abg-αβγ

Oops ... Ora il file è ancora in ANSI e indovina un po ', "αβγ" non occupa 6 byte, ma 3. Questo non è UTF-8 e questo causa altri problemi in seguito nella catena di sviluppo.


9
Garantire che vengano visualizzati byte spuri all'inizio del software non compatibile con BOM. Sìì.
Romain,

1
@Romain Muller: ad esempio PHP 5 genererà errori "impossibili" quando si tenta di inviare le intestazioni dopo la distinta base.
Piskvor ha lasciato l'edificio l'

5
αβγ non è ascii, ma può apparire in codifiche a 8 bit-ascii-bassed. L'uso di una distinta componenti disabilita un vantaggio di utf-8, la sua compatibilità con ascii (capacità di lavorare con applicazioni di lagacy in cui viene utilizzato puro ASCII).
ctrl-alt-delor,

1
Questa è la risposta sbagliata Una stringa con una DBA di fronte è qualcos'altro. Non dovrebbe essere lì e rovina tutto.
tchrist,

Senza DBA questo si apre come ANSI nella maggior parte degli editor. Sono assolutamente d'accordo. Se ciò accade, sei fortunato se hai a che fare con la tabella codici corretta, ma in effetti è solo un'ipotesi, perché la tabella codici non fa parte del file. Una distinta è.
luminoso

1

Ecco la mia esperienza con Visual Studio, Sourcetree e richieste pull di Bitbucket, che mi ha dato alcuni problemi:

Quindi risulta che la DBA con una firma includerà un carattere punto rosso su ogni file quando si esamina una richiesta pull (può essere abbastanza fastidioso).

Inserisci qui la descrizione dell'immagine

Se ci passi sopra, mostrerà un personaggio come "ufeff", ma si scopre che Sourcetree non mostra questi tipi di bytemark, quindi molto probabilmente finirà nelle tue richieste pull, il che dovrebbe essere ok perché è così che Visual Studio 2017 codifica ora nuovi file, quindi forse Bitbucket dovrebbe ignorarlo o farlo mostrare in un altro modo, maggiori informazioni qui:

Indicatore punto rosso BitBucket vista diff


-4

UTF con una distinta base è migliore se usi UTF-8 nei file HTML e se usi cirillico serbo, latino serbo, tedesco, ungherese o una lingua esotica nella stessa pagina.

Questa è la mia opinione (30 anni di informatica e settore IT).


1
Trovo che anche questo sia vero. Se si utilizzano caratteri al di fuori del primo set ASCII 255 e si omette la distinta componenti, i browser la interpretano come ISO-8859-1 e si ottengono caratteri confusi. Date le risposte di cui sopra, ciò sembra che i venditori di browser stiano facendo la cosa sbagliata quando non rilevano una DBA. Ma a meno che tu non lavori in Microsoft Edge / Mozilla / Webkit / Blink, non hai altra scelta che lavorare con i difetti che hanno queste app.
asontu,

UTF cosa? UTF-8? UTF-16? Qualcos'altro?
Peter Mortensen,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.