文字列書式、\uXXXX のままの String インスタンスなら、変換処理の必要性なくそのまま
インスタンスを扱うのであるが、文字列として \uXXXX を
通常の文字列(utf-8)に変換する場合の問題です。
文字列書式、\uXXXX
String str = "\u6f22\u5b57\uff1a\u6c0f\u540d"; // str = 漢字:氏名
\u → \\u になっている文字列を通常の文字列(utf-8)に変換する問題
String str = "\\u6f22\\u5b57\\uff1a\\u6c0f\\u540d";
\\u の後ろの Hex4文字を char 型に変換して読み込めば良いのだが、
間にASCII文字や他の文字が入っても Unicodeだけを変換する問題
String str = "\\u6f22\\u5b57_\\uff1a_\\u6c0f\\u540d"; // 期待値 = 漢字_:_氏名
という期待値を求めるには、単純に1文字ループや、\\\\u で区切ったループ処理ではとても辛い。
・\\uXXXX の正規表現 Matcher を生成
・Matcher をイテレータ処理で一致に対してUTF-8に変換
・イテレータを StremSupport でStream生成して、非変換と集約
ということをする必要がある。
以下のメソッドのとおりである。
・必要なインポート
import java.util.Iterator; import java.util.Spliterator; import java.util.Spliterators; import java.util.concurrent.atomic.AtomicInteger; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.StreamSupport;
・引数に、\\uXXXX が混ざった文字列を指定して変換
public String unicodeToUtf8(String ustr) { if (ustr==null) return null; AtomicInteger i = new AtomicInteger(0); Matcher m = Pattern.compile("\\\\u[0-9a-fA-F]{4}").matcher(ustr); return StreamSupport.stream(Spliterators.spliteratorUnknownSize(new Iterator<String>(){ @Override public boolean hasNext(){ return m.find(); } @Override public String next(){ return ustr.substring(i.getAndSet(m.end()), m.start()) + (char)(Integer.parseInt(m.group().substring(2), 16)); } }, Spliterator.ORDERED), false).collect(Collectors.joining()) + ustr.substring(i.get()); }