Closed3

macOSファイルシステムのUnicode正規化

けのびけのび

Webアプリケーションなどでファイルを扱う場面(アップロードなど)では注意した方が良いのでメモ。

Unicodeの正規化形式の概要

Unicodeの正規化形式に NFC (Normalization Form C)NFD (Normalization Form D) がある。

の文字を例に挙げる。見た目は同じでもバイト列が異なる。

  • NFC形式
    • U+表記 U+30D4
  • NFD形式
    • U+表記 U+30D2(ヒ) + U+309A(半濁点)

さらに、コード上で文字列を比較する処理がある場合は一致しないので注意が必要。 😢

console.log("ピ" === "ピ")
// false

ファイルを扱う場面でなぜ注意?

macOSのファイルシステムでは NFD が使われている。

macOSのFinderで任意のファイルにピの文字を入力して保存し、入力したファイル名をコピーして比較すると一致しないことが確認できる。

例えば、macOSのユーザーが、あるWebアプリケーションでファイル名に日本語文字が入ったファイルをアップロードし、ファイル名で検索しようとする。
ファイルアップロードする際にファイル名をNFC形式に正規化するなりしてストレージに登録しないと、検索にヒットしない場合がある。

一見、文字の見た目が同じなので上記のことをケアしないと、正規化形式の揺れによって実装者やアプリケーションユーザーを混乱させてしまう。

実装するアプリケーションでどちらの形式に統一するかは考慮したほうが良さそうな。 🤔

正規化方法

JavaScriptだとビルトインの関数があり、これを用いると良い。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/normalize

const fileName = "コピー.png"

// NFC形式に正規化
fileName.normalize("NFC")

// NFD形式に正規化
fileName.normalize("NFD")
けのびけのび

ASCIIの文字だと単一バイト表現なので今回のことは気にしなくても良いが、特に多言語で利用されるアプリケーションだと避けては通れないお話か。

このスクラップは2025/02/27にクローズされました