Cosa c'è di diverso tra UTF-8 e UTF-8 senza una distinta base ? Che è migliore?
Cosa c'è di diverso tra UTF-8 e UTF-8 senza una distinta base ? Che è migliore?
Risposte:
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.
Le altre eccellenti risposte hanno già risposto che:
EF BB BF
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:
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.
Esistono almeno tre problemi con l'inserimento di una distinta base nei file codificati UTF-8.
E, come altri hanno già detto, non è né sufficiente né necessario disporre di una DBA per rilevare che qualcosa è UTF-8:
cat
non ti darà un risultato pulito , un risultato che ha una DBA solo all'inizio. Se intendevi questo, allora è perché cat
funziona a livello di byte, non a livello di contenuti interpretati, e in modo simile cat
non può gestire le fotografie, diciamo. Tuttavia non fa molto male. Questo perché la distinta componenti codifica uno spazio senza interruzioni di larghezza zero.
Ecco alcuni esempi dell'utilizzo della distinta componenti che in realtà causa problemi reali e tuttavia molte persone non lo sanno.
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]
Vedi RFC 7159, Sezione 8.1 :
Le implementazioni NON DEVONO aggiungere un segno di ordine byte all'inizio di un testo 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).
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:
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.
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.
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.
Cosa c'è di diverso tra UTF-8 e UTF-8 senza BOM?
Risposta breve: in UTF-8, una DBA è codificata come byte EF BB BF
all'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 è.
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.
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 )
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.
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 type
e more
non si prevede che la distinta componenti sia presente. Se la distinta componenti è presente, può essere problematica come per altre applicazioni.
† Il chcp
comando offre supporto per UTF-8 ( senza DBA) tramite la tabella codici 65001 .
.htaccess
e gzip compression
in 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
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.
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.
Va notato che per alcuni file non è necessario disporre della DBA anche su Windows. Esempi sono SQL*plus
o VBScript
file. Nel caso in cui tali file contengano una distinta componenti, viene visualizzato un errore quando si tenta di eseguirli.
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.
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"
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.
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 .
chcp 65001
per 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.a
o echo אאא>a.a
per generare i caratteri nel file aa, e hai chcp 65001, verrà emesso senza DBA.
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.
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.
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
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:
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.
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.
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.
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.
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.
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).
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:
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).