Ajouter UTF-8 BOM à string/Blob

j'ai besoin d'ajouter un UTF-8 byte-order-mark aux données de texte générées du côté du client. Comment dois-je faire?

en utilisant new Blob(['xEFxBBxBF' + content]) donne '"my data"' , bien sûr.

N'a pas non plus fait 'uBBEFx22BF' travail (avec 'x22' == '"' étant le prochain caractère dans content ).

est-il possible de préparer le BOM UTF-8 en JavaScript à un texte généré?

Oui, j'ai vraiment besoin de l'UTF-8 BOM dans ce cas.

29
demandé sur kay 2013-07-26 14:37:13

3 réponses

Prepend \ufeff à la chaîne. Voir http://msdn.microsoft.com/en-us/library/ie/2yfce773 (v=94).aspx

Voir la discussion entre @jeff-fischer et @casey pour plus de détails sur l'UTF-8 et UTF-16 et de la NOMENCLATURE. Ce qui fait que ce qui précède fonctionne, c'est que la chaîne \ufeff est toujours utilisée pour représenter le BOM, indépendamment de L'UTF-8 ou UTF-16 utilisé.

Voir p.36 dans Le Standard Unicode 5.0, Chapitre 2 pour une explication détaillée. Une citation de cette page

au tableau 2-4, L'entrée d'ordre endian pour L'UTF-8 est marquée S / O parce que UTF-8 unités de code sont de 8 bits dans la taille, et les problèmes habituels de la machine les unités de code plus grandes ne s'appliquent pas. La commande sérialisé les octets ne doit pas s'écarter de l'ordre défini par l'UTF - 8 encodage. Utiliser d'une NOMENCLATURE est ni nécessaire ni recommandé pour UTF-8, mais peut être rencontré dans des contextes où les données UTF-8 est converti à partir d'autres formes d'encodage qui utilisent un BOM ou où le BOM est utilisé comme signature UTF-8.

79
répondu Erik Töyrä 2017-05-23 12:10:31

je suis en train d'éditer ma réponse originale. La réponse ci-dessus exige vraiment l'élaboration car il s'agit d'une solution alambiquée par noeud.js.

La réponse courte est oui, ce code fonctionne.

la longue réponse est, non, FEFF n'est pas le point d'ordre pour utf-8. Apparemment, node a pris une sorte de raccourci pour écrire des encodages dans des fichiers. FEFF est L'encodage UTF16 Little Endian comme on peut le voir dans l'ordre de Byte Mark wikipedia article et peut également être vu dans un éditeur de texte binaire après avoir écrit le fichier. J'ai vérifié c'est le cas.

http://en.wikipedia.org/wiki/Byte_order_mark#Representations_of_byte_order_marks_by_encoding

Apparemment, Noeud.JS utilise le \ufeff pour désigner tout numéro d'encodage . Il prend le marqueur \ufeff et le convertit dans le bon marqueur d'ordre des octets basé sur le paramètre 3rd options du fichier writeFile. Le troisième paramètre que vous passez dans la chaîne d'encodage. Nœud.JS prend cette chaîne de codage et convertit l'octet fixe \ufeff codant dans n'importe laquelle des marques d'ordre d'octet de l'encodage réel.

UTF-8 Exemple:

fs.writeFile(someFilename, '\ufeff' + html, { encoding: 'utf8' }, function(err) {
   /* The actual byte order mark written to the file is EF BB BF */
}

UTF-16 Little Endian exemple:

fs.writeFile(someFilename, '\ufeff' + html, { encoding: 'utf16le' }, function(err) {
   /* The actual byte order mark written to the file is FF FE */
}

Donc, comme vous pouvez le voir le \ufeff est simplement un marqueur indiquant un nombre de codages. Le codage réel qui le rend dans le fichier dépend directement l'option d'encodage spécifiée. Le marqueur utilisé dans la chaîne de caractères est vraiment sans rapport avec ce qui est écrit dans le fichier.

je soupçonne que le raisonnement derrière ceci est parce qu'ils ont choisi de ne pas écrire des marques d'ordre d'octet et la marque de 3 octets pour UTF-8 n'est pas facilement encodé dans la chaîne javascript pour être écrit sur le disque. Ainsi, ils ont utilisé le UTF16LE BOM comme un marqueur placé dans la chaîne qui est substituée au moment de l'écriture.

8
répondu Jeff Fischer 2016-07-22 22:07:14

j'ai eu le même problème et c'est la solution je suis venu avec:

var blob = new Blob([
                    new Uint8Array([0xEF, 0xBB, 0xBF]), // UTF-8 BOM
                    "Text",
                    ... // Remaining data
                    ],
                    { type: "text/plain;charset=utf-8" });

en utilisant Uint8Array empêche le navigateur de convertir ces octets en chaîne (testé sur Chrome et Firefox).

vous devez remplacer text/plain par votre type MIME désiré.

5
répondu carlosrafaelgn 2016-12-28 13:25:54