web-dev-qa-db-fra.com

Ajout d'une nomenclature UTF-8 à une chaîne / un blob

J'ai besoin d'ajouter une marque d'ordre d'octets UTF-8 aux données de texte générées côté client. Comment je fais ça?

L'utilisation de new Blob(['\xEF\xBB\xBF' + content]) donne '"my data"', bien sûr.

'\uBBEF\x22BF' travailler avec '\x22' == '"' étant le caractère suivant dans content).

Est-il possible d'ajouter la nomenclature UTF-8 en JavaScript à un texte généré?

Oui, j'ai vraiment besoin de la nomenclature UTF-8 dans ce cas.

42
kay

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

Voir la discussion entre @ jeff-fischer et @ caseypour plus de détails sur UTF-8 et UTF-16 et la nomenclature. Ce qui fait que le travail ci-dessus est que la chaîne \ufeff est toujours utilisé pour représenter la nomenclature, quel que soit l'UTF-8 ou l'UTF-16 utilisé.

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

L'entrée d'ordre endian pour UTF-8 dans le tableau 2-4 est marquée N/A car les unités de code UTF-8 ont une taille de 8 bits, et les problèmes de machine habituels d'ordre endian pour les unités de code plus grandes ne s'appliquent pas. L'ordre sérialisé des octets ne doit pas s'écarter de l'ordre défini par le formulaire de codage UTF-8. L'utilisation d'une nomenclature n'est ni requise ni recommandée pour UTF-8, mais peut être rencontrée dans des contextes où les données UTF-8 sont converties à partir d'autres formes de codage qui utilisent une nomenclature ou lorsque la nomenclature est utilisée comme signature UTF-8.

J'ai eu le même problème et c'est la solution que j'ai trouvée:

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 avec le type MIME souhaité.

13
carlosrafaelgn

J'édite ma réponse d'origine. La réponse ci-dessus exige vraiment une élaboration car il s'agit d'une solution compliquée de Node.js.

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

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

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

Apparemment, Node.JS utilise le\ufeff pour signifier n'importe quel nombre d'encodage . Il prend le marqueur\ufeff et le convertit en la marque d'ordre d'octets correcte basée sur le 3ème paramètre d'options de writeFile. Le 3ème paramètre que vous passez dans la chaîne de codage. Node.JS prend cette chaîne de codage et convertit le codage d'octets fixes\ufeff en l'un des repères d'ordre d'octets du codage réel.

Exemple UTF-8:

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

Exemple UTF-16 Little Endian:

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 n'importe quel nombre d'encodages résultants. L'encodage réel qui en fait le fichier dépend directement de l'option d'encodage spécifiée. Le marqueur utilisé dans la chaîne n'est vraiment pas pertinent pour ce qui est écrit dans le fichier.

Je soupçonne que le raisonnement derrière cela est parce qu'ils ont choisi de ne pas écrire de marques d'ordre d'octets et que la marque de 3 octets pour UTF-8 n'est pas facilement encodée dans la chaîne javascript à écrire sur le disque. Ainsi, ils ont utilisé la nomenclature UTF16LE comme marque d'espace réservé dans la chaîne qui est substituée au moment de l'écriture.

13
Jeff Fischer

Voici ma solution:

var blob = new Blob(["\uFEFF"+csv], {
type: 'text/csv; charset=utf-18'
});
0
Santy SC