web-dev-qa-db-ja.com

UTF-8 BOMをstring / Blobに追加する

クライアント側で生成されたテキストデータにUTF-8バイトオーダーマークを追加する必要があります。それ、どうやったら出来るの?

new Blob(['\xEF\xBB\xBF' + content])を使用すると、'"my data"'、 もちろん。

'\uBBEF\x22BF' と連携 '\x22' == '"'contentの次の文字です。

JavaScriptのUTF-8 BOMを生成されたテキストの先頭に追加することはできますか?

はい、この場合は本当にUTF-8 BOMが必要です。

42
kay

\ufeffを文字列の先頭に追加します。 http://msdn.Microsoft.com/en-us/library/ie/2yfce773(v = vs.94).aspx を参照してください

@ jeff-fischer@ caseyTF-8およびUTF-16の詳細について とBOMの間の議論を参照してください。実際に上記の作業を行うのは、使用されているUTF-8またはUTF-16に関係なく、文字列\ufeffが常にBOMを表すために使用されることです。

詳細な説明については、 The Unicode Standard 5.0、Chapter 2 のp.36を参照してください。そのページからの引用

表2-4のUTF-8のエンディアン順序エントリは、UTF-8コード単位のサイズが8ビットであり、より大きなコード単位のエンディアン順序の通常のマシンの問題が適用されないため、N/Aとマークされます。バイトのシリアル化された順序は、UTF-8エンコーディング形式で定義された順序から逸脱してはなりません。 UTF-8ではBOMの使用は必須でも推奨でもありませんが、BOMを使用する他のエンコード形式からUTF-8データが変換されるコンテキスト、またはBOMがUTF-8署名として使用されるコンテキストで発生する可能性があります。

私は同じ問題を抱えていましたが、これが私が思いついた解決策です:

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

Uint8Arrayを使用すると、ブラウザがこれらのバイトを文字列に変換できなくなります(ChromeおよびFirefoxでテスト済み)。

text/plainを希望のMIMEタイプに置き換える必要があります。

13
carlosrafaelgn

元の回答を編集しています。上記の答えは、Node.jsによる複雑なソリューションであるため、詳細な説明が必要です。

簡単な答えは、はい、このコードは機能します。

長い答えは、いいえ、FEFFはutf-8のバイトオーダーマークではありません。どうやらノードはファイル内のエンコーディングを書くためのある種のショートカットを取っているようです。 FEFFは、バイトオーダーマークウィキペディアの記事で見ることができるUTF16リトルエンディアンエンコーディングであり、ファイルを書き込んだ後にバイナリテキストエディターで表示することもできます。これが事実であることを確認しました。

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

どうやら、Node.JSは\ ufeffを使用して、任意の数のエンコードを示します。\ufeffマーカーを取得し、writeFileの3番目のオプションパラメーターに基づいて正しいバイトオーダーマークに変換します。エンコード文字列で渡す3番目のパラメーター。 Node.JSはこのエンコード文字列を受け取り、converted\ ufeff固定バイトエンコードを実際のエンコードのバイトオーダーマークのいずれかに変換します。

UTF-8の例:

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

UTF-16リトルエンディアンの例:

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

したがって、ご覧のとおり、\ ufeffは、結果のエンコーディングをいくつでも示す単なるマーカーです。それをファイルにする実際のエンコーディングは、指定されたエンコーディングオプションに直接依存します。文字列内で使用されるマーカーは、実際にファイルに書き込まれるものとは無関係です。

この背後にある理由は、バイトオーダーマークを書き込まないことを選択し、UTF-8の3バイトマークがディスクに書き込まれるjavascript文字列に簡単にエンコードされないためだと思われます。そのため、書き込み時に置換される文字列内のプレースホルダーマークとしてUTF16LE BOMを使用しました。

13
Jeff Fischer

これは私の解決策です:

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