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

Cosa c’è di diverso tra UTF-8 e UTF-8 senza una BOM ? Che è migliore?

Il BOM UTF-8 è una sequenza di byte (EF BB BF) che consente al lettore di identificare un file come codificato in UTF-8.

Normalmente, il BOM viene utilizzato per segnalare l’endianità di una codifica, ma poiché endianness è irrilevante per UTF-8, il BOM non è necessario.

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

2.6 Schemi di codifica

… L’uso di una BOM non è richiesto né raccomandato per UTF-8, ma può essere incontrato in contesti in cui i dati UTF-8 vengono convertiti da altri moduli di codifica che utilizzano una BOM o dove la BOM viene utilizzata come firma UTF-8 . Vedere la sottosezione “Byte Order Mark” nella Sezione 16.8, Specials , per ulteriori informazioni.

Le altre eccellenti risposte hanno già risposto che:

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

Ma, come informazioni aggiuntive a questo, il BOM per UTF-8 potrebbe essere un buon modo per “annusare” se una stringa è stata 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 interessante riconoscere la codifica di un contenuto di un file guardando i primi byte, non dovresti fare affidamento su questo, come mostrato nell’esempio sopra

Le codifiche dovrebbero essere conosciute, non divinizzate.

Ci sono almeno tre problemi con l’inserimento di una BOM in file codificati UTF-8.

  1. I file che non contengono testo non sono più vuoti perché contengono sempre il BOM.
  2. I file che contengono testo all’interno del sottoinsieme ASCII di UTF-8 non sono più ASCII perché il BOM non è ASCII, il che rende obsoleti alcuni strumenti esistenti e può essere imansible per gli utenti sostituire tali strumenti legacy.
  3. Non è ansible concatenare più file insieme perché ogni file ha ora una distinta materiali all’inizio.

E, come altri hanno già detto, non è né sufficiente né necessario avere una distinta base per rilevare che qualcosa è UTF-8:

  • Non è sufficiente perché una sequenza di byte arbitraria può capitare di iniziare con la sequenza esatta che costituisce la BOM.
  • Non è necessario perché puoi semplicemente leggere i byte come se fossero UTF-8; se ciò riesce, è, per definizione, UTF-8 valido.

È una vecchia domanda con molte buone risposte, ma una cosa dovrebbe essere aggiunta.

Tutte le risposte sono molto generali. Quello che vorrei aggiungere sono esempi dell’utilizzo delle BOM che effettivamente causano problemi reali e tuttavia molte persone non ne sono a conoscenza.

La distinta base interrompe gli script

Script di shell, script Perl, script Python, script di Ruby, script Node.js o qualsiasi altro eseguibile che deve essere eseguito da un interprete – tutto inizia con una riga di 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 tale script. Se lo script è codificato in UTF-8, si potrebbe essere tentati di includere una distinta materiali all’inizio. Ma in realtà il “#!” i personaggi non sono solo personaggi. Sono in effetti un numero magico che sembra essere composto da due caratteri ASCII. Se metti qualcosa (come una BOM) prima di quei caratteri, 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 è comunemente usato per script e altri file di testo su sistemi attuali come Unix. Tuttavia, i file UTF-8 possono iniziare con il byte order mark (BOM) opzionale; se la funzione “exec” rileva in modo specifico i byte 0x23 e 0x21, la presenza della distinta componenti (0xEF 0xBB 0xBF) prima dello shebang impedirà l’esecuzione dell’interprete dello script. Alcune autorità raccomandano di non utilizzare il codice di ordinazione dei byte in script POSIX (tipo Unix), [14] per questo motivo e per una maggiore interoperabilità e preoccupazioni filosofiche. Inoltre, in UTF-8 non è necessario un contrassegno dell’ordine dei byte, poiché tale codifica non ha 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 contrassegno di ordine dei byte all’inizio di un testo JSON.

BOM è ridondante in JSON

Non solo è illegale in JSON, non è nemmeno necessario determinare la codifica dei caratteri perché esistono metodi più affidabili per determinare in modo non ambiguo sia la codifica dei caratteri che l’endianness utilizzati in qualsiasi stream JSON (vedere questa risposta per i dettagli).

La distinta base interrompe 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 endianness di JSON, esaminando i primi 4 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 a questo:

 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 3 NUL quindi non verrà riconosciuto
  3. UTF-16BE ha solo 1 NUL nei primi 4 byte, quindi non verrà riconosciuto
  4. UTF-16LE ha solo 1 NUL nei primi 4 byte, quindi non verrà riconosciuto

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

Inoltre, se i test di implementazione per JSON validi come raccomando, rifiuteranno anche l’input che è effettivamente codificato come UTF-8 perché non inizia con un carattere ASCII <128 come dovrebbe, secondo l'RFC.

Altri formati di dati

La BOM in JSON non è necessaria, è illegale e interrompe il software che funziona correttamente secondo la RFC. Dovrebbe essere un gentiluomo non usarlo poi eppure, ci sono sempre persone che insistono per rompere JSON usando BOM, commenti, diverse regole di quotazione o diversi tipi di dati. Naturalmente chiunque è libero di usare cose come BOM o qualsiasi altra cosa se ne ha bisogno – semplicemente non chiamarlo JSON allora.

Per altri formati di dati oltre a JSON, dai un’occhiata a come sembra. Se le sole 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 la endianità dei tuoi dati. Aggiunta di distinte materiali anche come funzionalità opzionale renderebbe solo più complicato e sobject a errori.

Altri usi di BOM

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 scripting e serializzazione perché è un esempio di caratteri distinta base che causano problemi reali.

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

Risposta breve: in UTF-8, una distinta materiali viene codificata come byte EF BB BF all’inizio del file.

Risposta lunga:

Originariamente, era previsto che Unicode venisse codificato in UTF-16 / UCS-2. Il BOM è stato progettato per questo modulo di codifica. Quando si hanno unità di codice a 2 byte, è necessario indicare in quale ordine sono presenti questi due byte e una convenzione comune per farlo consiste nell’includere il carattere U + FEFF come un “Byte Order Mark” all’inizio dei dati. Il carattere U + FFFE è permanentemente non assegnato in modo che la sua presenza possa essere utilizzata per rilevare l’ordine dei byte errato.

UTF-8 ha lo stesso ordine di byte indipendentemente dalla endianità della piattaforma, quindi non è necessario un contrassegno di ordine byte. Tuttavia, può verificarsi (come la sequenza byte EF BB FF ) nei dati che sono stati 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 consiglia. Provoca problemi con il software non BOM-aware.

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

UTF-8 con BOM è meglio identificato. 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 un BOM, Excel pensa che sia ANSI e mostri senza senso. Dopo aver aggiunto “EF BB BF” nella parte anteriore (ad esempio, ri-salvando utilizzando Blocco note con UTF-8 o Notepad ++ con UTF-8 con BOM), Excel lo apre correttamente.

La pre-registrazione del carattere BOM in file di testo Unicode è raccomandata dalla RFC 3629: “UTF-8, un formato di trasformazione di ISO 10646”, novembre 2003 su http://tools.ietf.org/html/rfc3629 (quest’ultima informazione si trova in: http://www.herongyang.com/Unicode/Notepad-Byte-Order-Mark-BOM-FEFF-EFBBBF.html )

BOM tende a boom (nessun gioco di parole (sic)) da qualche parte, da qualche parte. E quando esplode (ad esempio, non viene riconosciuto da browser, editor, ecc.), Si presenta 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 sperimentato durante i discorsi di Obama su Twitter .

È molto fastidioso quando si presenta in luoghi difficili da eseguire il debug o quando il test viene trascurato. Quindi è meglio evitarlo a meno che tu non debba usarlo.

Domanda: Qual è la differenza tra UTF-8 e UTF-8 senza una BOM? Che è migliore?

Ecco alcuni estratti dall’articolo di Wikipedia sul byte order mark (BOM) che credo offrano una risposta solida a questa domanda.

Sul significato di BOM e UTF-8:

Unicode Standard consente la distinta componenti in UTF-8 , ma non richiede o consiglia l’utilizzo. L’ordine dei byte non ha significato in UTF-8, quindi il suo uso solo in UTF-8 è quello di segnalare all’inizio che il stream di testo è codificato in UTF-8.

Argomento per NON usare un BOM:

La motivazione principale per non utilizzare una distinta base è la retrocompatibilità con il software che non è a conoscenza di Unicode … Un’altra motivazione per non utilizzare una distinta base è incoraggiare UTF-8 come codifica “predefinita”.

Argomento PER L’ utilizzo di un BOM:

L’argomento per l’utilizzo di un BOM è che senza di esso è richiesta un’analisi euristica per determinare quale codifica del carattere sta utilizzando un file. Storicamente tale analisi, per distinguere le 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 per Unicode.

I programmatori presumono erroneamente che il rilevamento di UTF-8 sia ugualmente difficile (non è perché la 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 che supportano Unicode eseguono tale analisi e si affidano invece al BOM.

In particolare, compilatori e 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 distinta base e aggiungerà una distinta base all’avvio quando si salva testo come UTF-8. Google Documenti aggiungerà una BOM quando un documento di Microsoft Word viene scaricato come file di testo normale.

Su quale è meglio, CON o SENZA il BOM:

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 materiali solo se la compatibilità con un’applicazione software è assolutamente essenziale.

Si noti inoltre che mentre l’articolo di riferimento di Wikipedia indica che molte applicazioni Microsoft si basano sul BOM per rilevare correttamente UTF-8, questo non è il caso per tutte le applicazioni Microsoft. Ad esempio, come indicato da @barlop , quando si utilizza il prompt dei comandi di Windows con UTF-8 , i comandi di questo type e more non si aspettano che la distinta componenti sia presente. Se il BOM è presente, può essere problematico come lo è per altre applicazioni.


† Il comando chcp offre il supporto per UTF-8 ( senza il BOM) tramite la code page 65001 .

Citato nella parte inferiore della pagina di Wikipedia su BOM: http://en.wikipedia.org/wiki/Byte-order_mark#cite_note-2

“L’uso di una distinta base non è né richiesto né consigliato 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 distinta componenti o in cui la distinta componenti viene utilizzata come firma UTF-8”

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

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

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

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

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

Il BOM è solitamente utile per determinare la endianità della codifica, che non è richiesta per la maggior parte dei casi d’uso.

Inoltre, la distinta base può essere rumore / dolore non necessario per quei consumatori che non conoscono o si preoccupano di ciò e possono causare confusione all’utente.

Quando vuoi visualizzare le informazioni codificate in UTF-8, potresti non avere problemi. Dichiarare ad esempio un documento HTML come UTF-8 e si avrà tutto ciò che viene visualizzato nel browser che è contenuto nel corpo del documento.

Ma questo non è il caso quando abbiamo file di testo, CSV e XML, sia su Windows o 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 stringa di dati contenente lettere francesi, che dovevano essere salvate come XML per la syndication. Senza creare un file UTF-8 sin dall’inizio (modificando le opzioni in IDE e “Crea nuovo file”) o aggiungendo il BOM all’inizio del file

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

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

Va notato che per alcuni file non è necessario avere il BOM anche su Windows. Esempi sono i file SQL*plus o VBScript . Nel caso in cui tali file contengano una distinta base si ottiene 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, potrebbe eventualmente interrompere le applicazioni meno recenti che avrebbero altrimenti interpretato il file come semplice ASCII. Queste applicazioni falliranno sicuramente quando si imbatteranno in un carattere non ASCII, quindi a mio avviso la BOM dovrebbe essere aggiunta solo quando il file può, e dovrebbe, non essere più interpretato come semplice ASCII.

Edit: Voglio solo chiarire che preferisco non avere il BOM, aggiungerlo se qualche vecchia spazzatura si rompe con esso, e la sostituzione di quell’applicazione legacy non è fattibile.

Non fare nulla aspettarsi una distinta base per UTF8.

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 si salva come UTF-8, nessun BOM (ad esempio in BBEdit ) andrà tutto bene.

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

Come accennato, qualsiasi utilizzo della BOM UTF (Byte Order Mark) nel determinare se una stringa sia UTF-8 o meno è una supposizione istruita. Se sono disponibili metadati corretti (come charset="utf-8" ), allora sai già cosa dovresti usare, ma altrimenti dovrai testare e formulare alcune ipotesi. Ciò implica verificare se il file da cui proviene una stringa inizia con il codice byte esadecimale, EF BB BF.

Se viene trovato un codice byte corrispondente al BOM UTF-8, la probabilità è abbastanza alta da supporre che sia UTF-8 e si può andare da lì. Quando è costretta a fare questa ipotesi, tuttavia, un ulteriore controllo degli errori durante la lettura sarebbe comunque una buona idea nel caso in cui qualcosa dovesse apparire confuso. Dovresti solo supporre che una distinta base non sia UTF-8 (cioè latin-1 o ANSI) se l’input non dovrebbe essere UTF-8 in base alla sua origine. Se non esiste una distinta base, tuttavia, è ansible determinare semplicemente se si suppone che sia UTF-8 convalidando la codifica.

Perché una BOM non è raccomandata?

  1. Un software non compatibile con Unicode o scarsamente conforms può presupporre che sia latino-1 o ANSI e che non rimuova il BOM dalla stringa, il che può ovviamente causare problemi.
  2. Non è davvero necessario (basta controllare se il contenuto è conforms e utilizzare sempre UTF-8 come fallback quando non è ansible trovare la codifica conforms)

Quando dovresti codificare con una BOM?

Se non sei in grado di registrare i metadati in altro modo (tramite un tag charset o meta del file system) e i programmi in uso come BOM, dovresti codificare con una BOM. Ciò è particolarmente vero su Windows in cui si presume che qualsiasi cosa senza una distinta base utilizzi una codepage legacy. Il BOM indica programmi come Office che, sì, il testo in questo file è Unicode; ecco la codifica usata.

When it comes down to it, the only files I ever really have problems with are CSV. Depending on the program, it either must, or must not have a BOM. For example, if you’re using Excel 2007+ on Windows, it must be encoded with a BOM if you want to open it smoothly and not have to resort to importing the data.

As mentioned above, UTF-8 with BOM may cause problems with non-BOM-aware (or compatible) software. I once edited HTML files encoded as UTF-8 + BOM with the Mozilla-based KompoZer , as a client required that WYSIWYG program.

Invariably the layout would get destroyed when saving. It took my some time to fiddle my way around this. These files then worked well in Firefox, but showed a CSS quirk in Internet Explorer destroying the layout, again. After fiddling with the linked CSS files for hours to no avail I discovered that Internet Explorer didn’t like the BOMfed HTML file. Never again.

Also, I just found this in Wikipedia:

The shebang characters are represented by the same two bytes in extended ASCII encodings, including UTF-8, which is commonly used for scripts and other text files on current Unix-like systems. However, UTF-8 files may begin with the optional byte order mark (BOM); if the “exec” function specifically detects the bytes 0x23 0x21, then the presence of the BOM (0xEF 0xBB 0xBF) before the shebang will prevent the script interpreter from being executed. Some authorities recommend against using the byte order mark in POSIX (Unix-like) scripts,[15] for this reason and for wider interoperability and philosophical concerns

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

The byte order mark (BOM) is a Unicode character used to signal the endianness (byte order) of a text file or stream. Its code point is U+FEFF. BOM use is optional, and, if used, should appear at the start of the text stream. Beyond its specific use as a byte-order indicator, the BOM character may also indicate which of the several Unicode representations the text is encoded in.

Always using a BOM in your file will ensure that it always opens correctly in an editor which supports UTF-8 and BOM.

My real problem with the absence of BOM is the following. Suppose we’ve got a file which contains:

 abc 

Without BOM this opens as ANSI in most editors. So another user of this file opens it and appends some native characters, for example:

 abg-αβγ 

Oops… Now the file is still in ANSI and guess what, “αβγ” does not occupy 6 bytes, but 3. This is not UTF-8 and this causes other problems later on in the development chain.

The Unicode Byte Order Mark (BOM) FAQ provides a concise answer:

Q: How I should deal with BOMs?

A: Here are some guidelines to follow:

  1. A particular protocol (eg Microsoft conventions for .txt files) may require use of the BOM on certain Unicode data streams, such as files. When you need to conform to such a protocol, use a BOM.

  2. Some protocols allow optional BOMs in the case of untagged text. In those cases,

    • Where a text data stream is known to be plain text, but of unknown encoding, BOM can be used as a signature. If there is no BOM, the encoding could be anything.

    • Where a text data stream is known to be plain Unicode text (but not which endian), then BOM can be used as a signature. If there is no BOM, the text should be interpreted as big-endian.

  3. Some byte oriented protocols expect ASCII characters at the beginning of a file. If UTF-8 is used with these protocols, use of the BOM as encoding form signature should be avoided.

  4. Where the precise type of the data stream is known (eg Unicode big-endian or Unicode little-endian), the BOM should not be used. In particular, whenever a data stream is declared to be UTF-16BE, UTF-16LE, UTF-32BE or UTF-32LE a BOM must not be used.

UTF with BOM is better if you use UTF-8 in HTML files, if you use Serbian Cyrillic, Serbian Latin, German, Hungarian or something exotic language in the same page. That is my opinion (30 years of computing and IT industry).