Unicode のスペースは色々あるし、半角スペースと &nbsp は同じでもない

f:id:Naotsugu:20210915215607p:plain


はじめに

  • 通常目にするスペースには、半角スペース と全角スペース   があるが、Unicode の定義上でスペースに分類されるものは(Unicodeのバージョンによっても異なるが)18種類存在する

  • HTML で良く目にする文字実体参照の   は、このスペースでの改行を禁止(No-Break)するもので、半角スペースとは異なる

  • Java の String.trim() でトリムされるスペースは、半角スペース U+0020

  • Java の String.strip() の場合は、ほとんどのスペースがトリムされるが、No-Break なスペースはトリムされない(つまり   なスペースはトリムされない)


Unicode の White_Space(Zs) カテゴリ

Unicode でホワイトスペース(Zs カテゴリ)に分類されるものは以下がある。

Code Point Name 説明
U+0020 Space 半角スペース 通常は 1/4 em の幅
U+00A0 No-Break Space &nbsp Space と同じ幅。No-Break
U+1680 Ogham Space mark オガム文字のスペース(ダッシュで表示される)
U+180E Mongolian Vowel Separator モンゴル語の​​母音区切り
U+2000 En Quad 1/2 em 幅
U+2001 Em Quad 1 em 幅 (フォントの高さと同じ)
U+2002 En Space   1/2 em
U+2003 Em Space   1 em
U+2004 Three-Per-Em Space 1/3 em
U+2005 Four-Per-Em Space 1/4 em
U+2006 Six-Per-Em Space 1/6 em
U+2007 Figure Space(No-Break) 固定幅フォントの数字と同じ幅。No-Break
U+2008 Punctuation Space ピリオドの幅
U+2009 Thin Space   1/5 em
U+200A Hair Space Thin Space よりさらに狭い
U+202F Narrow No-Break Space 狭い&nbsp。No-Break
U+205F Medium Mathematical Space 4/18 em (Unicode 4.0〜)
U+3000 Idepgraphic Space 全角スペース
  • 横幅が異なるスペースと、全角スペースなどの各国語で多数存在
  • No-Break が付くものは、このスペースで改行が行われないもの
  • そもそも &nbsp は半角スペースと同じではない


Zs カテゴリには分類されないが、ゼロ幅のスペースも存在する。

Code Point Name 説明
U+200B Zero Width Space ゼロ幅のスペース
U+FEFF Zero Width No-Break Space ゼロ幅の &nbsp
  • ゼロ幅のスペースは(単語を詰めて表示したまま)単語中の改行ポイントとなる


Java における trim と strip

String.trim() は、半角スペースのU+0020 よりも小さなコードポイントがトリムされる。 に加え、\r \n ... といった制御文字が削除対象となる。

str.trim();

つまり、全角スペースや &nbsp はトリムされない。


Java11 からは String.strip() が使え、その他のホワイトスペースもトリムされる(全角スペースはトリムされるが &nbsp はトリムされない)。

str.strip();

String.strip()Character.isWhitespace() でホワイトスペースの判定を行っている。

public static boolean isWhitespace(int codePoint) {
    return CharacterData.of(codePoint).isWhitespace(codePoint);
}

Character.isWhitespace() の JavaDoc は以下のようになっている。

指定された文字 (Unicode コードポイント) が Java の基準に従った空白かどうかを判定します。次の基準のどれかを満たす場合にだけ、Java の空白文字になります。

  • Unicode の空白文字 (SPACE_SEPARATOR、LINE_SEPARATOR、または PARAGRAPH_SEPARATOR) であるが、改行なしの空白 ('\u00A0'、'\u2007'、'\u202F') ではない。
  • '\t' (U+0009 水平タブ) である。
  • '\n' (U+000A 改行) である。
  • '\u000B' (U+000B 垂直タブ) である。
  • '\f' (U+000C フォームフィード) である。
  • '\r' (U+000D 復帰) である。
  • '\u001C' (U+001C ファイル区切り文字) である。
  • '\u001D' (U+001D グループ区切り文字) である。
  • '\u001E' (U+001E レコード区切り文字) である。
  • '\u001F' (U+001F 単位区切り文字) である。

SPACE_SEPARATOR は、Unicode の Zs カテゴリで、前述の一覧にあるものを指す。 ただし、No-Break である U+00A0, U+2007, U+202F の3つは除外となる。

LINE_SEPARATOR は Unicode の Zl カテゴリで U+2028PARAGRAPH_SEPARATORは、Unicode の Zp カテゴリで U+2029 これらは ASCII 範囲外にある制御文字であり、各種の環境で良くトラブルの元になるヤツ。何も言わずにスペースに置換してあげるのが大人な対応。

その他は各種の制御コードがトリムされる。

HTML の文字参照 &nbsp に該当する U+00A0 はトリムされないので少し注意した方が良いかもしれない。