1
0

More than 3 years have passed since last update.

"hoge hoge".equals("hoge hoge") // false

Last updated at Posted at 2020-01-11

この間起こったこと

先日、HTMLファイルを取り込んで文字を色々するみたいなことをやっていた時のこと。

String str1 = "hoge hoge";
String str2 = anyElement; // HTMLファイルから取り込んだ"hoge hoge"

System.out.println(str1.equals(str2)); 
// false

なんとfalseが出力されました。え、false...?
初めはString#equalsのバグか?と思ったのですが、まあそんな訳ないと思うので
色々調べてみました。

試しにcharで見てみる

ということで先ほどの二つの文字列をString#getBytesでUTF-8にしたら以下のようになりました。

str1 : [104, 111, 103, 101, 32, 104, 111, 103, 101]
str2 : [104, 111, 103, 101, -62, -96, 104, 111, 103, 101]

ん?

-62, -96 ...!?

なんやこれ!!!!

&nbsp(0xC2, 0xA0);

ノーブレークスペース - Wikipedia
↑0xC2, 0xA0の2バイトで表されるのは「ノーブレークスペース」というやつらしい。

どうもHTMLファイル上のnbspみたいなやつは、UTF-8では通常の半角スペース(0x20)ではなく
0xC2 0xA0の2バイトで表現されるようです。

標準出力に出してもただの半角スペースにしか見えません。罠だ...

通常の半角スペースじゃないと困る

そうなると文字列の処理上困ることがあります。
以下は半角スペースが全てノーブレークスペースの場合です。

String hoge = "a b c".split(" ");
// hoge = ["a b c"]
// ["a", "b", "c"]じゃないの...?

String fuga = "a b c".replaceAll(" ", "d");
// fuga = "a b c"
// "adbdc"じゃないの...?

罠だ...
しかし、例えば以下のようにすれば問題ありません。

public static final byte[] NBSP = {(byte)0xC2, (byte)0xA0}; 

String hoge = "a b c".split("[ |" + new String(NBSP) + "]");
// hoge = ["a", "b", "c"]

String fuga = "a b c"
      .replaceAll("[ |" + new String(NBSP) + "]", "d")
// fuga = "adbdc"

replaceAllもsplitも引数には正規表現をとるので、
[(半角スペース)|(ノーブレークスペース)]とするとどっちかは引っ掛かります。

まとめ

もう誰もノーブレークスペースで悩みませんように...

1
0
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0