5
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Java を使うWeb アプリの文字コードを Shift_JIS から UTF-8 に変更する場合の考慮点

Posted at

概要

昔からあるWebアプリケーションのHTML文字コード設定をUTF-8に変える時のポイントをまとめてみる。

前提

  • Webページの文字コード設定をShift_JISからUTF-8へ変更する
  • 利用したソフトウェアは以下
  • Java, Liberty, ChromeはmacOS、Db2はコンテナで稼働させる

Db2環境構築

env_list という名前で以下の内容のファイルを作っておく

LICENSE=accept
DB2INSTANCE=db2inst1
DB2INST1_PASSWORD=password
DBNAME=testdb
BLU=false
ENABLE_ORACLE_COMPATIBILITY=false
UPDATEAVAIL=NO
TO_CREATE_SAMPLEDB=false
REPODB=false
IS_OSXFS=false
PERSISTENT_HOME=true
HADR_ENABLED=false
ETCD_ENDPOINT=
ETCD_USERNAME=
ETCD_PASSWORD=
# Docker環境の構築
brew install docker docker-machine
docker-machine create --driver virtualbox default
eval $(docker-machine env)
docker-machine ip

# Db2コンテナの稼働
docker login
docker pull store/ibmcorp/db2_developer_c:11.1.4.4-x86_64
docker run -h db2server --name db2server --detach --privileged=true -p 50000:50000 -p 55000:55000 --env-file env_list store/ibmcorp/db2_developer_c:11.1.4.4-x86_64
docker exec -it db2server bash

# ibm-943コードページのデータベース作成
su - db2inst1
db2 create db ibm943db using codeset ibm-943 territory jp collate using identity

HTMLの変更箇所

<!doctype html>
  <html lang="en">
  <head>
    <meta charset="utf-8">
    <title>title</title>
  </head>
  <body>
    ...

JSPの変更箇所

HTTPレスポンスのcontent-typeとJSPファイル自体の文字コードは以下のように指定する

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" %>

WebページをUTF-8に変えると何が起きるか

ここからが本題。Webページを変更した時にサーバーサイドではどんな対処が必要なのかまとめてみる。

ブラウザからサーバーへ送信されるデータの文字参照が変わる

ユーザーが入力した文字によっては、ブラウザによって数値文字参照へ変換されて送信される。Shift_JISを利用する場合と、UTF-8を利用する場合で数値文字参照へ変換される文字が異なる。例えば、😀という絵文字はWebページがShift_JISの場合、&#128512;に変換されるが、UTF-8の場合は😀がそのまま送信される。以下の例では、¢、𠮷などで数値文字参照が利用される。

ユーザーの入力 Unicodeコードポイント Formエンコードデータ(Shift_JIS)の場合 Formエンコードデータ(UTF-8)の場合 備考
a U+0061 a a
& U+0026 &(%26) &(%26)
¢ U+00A2 &#162;(%26%23162%3B) ¢(%C2%A2) CENT SIGN. Shift_JIS に存在しない文字
U+FFE0 ¢(%81%91) ¢(%EF%BF%A0) FULLWIDTH CENT SIGN
U+2014 &#8212;(%26%238212%3B) —(%E2%80%94) EM DASH
U+2015 ―(%81%5C) ―(%E2%80%95) HORIZONTAL BAR
U+FF0D -(%81%7C) -(%EF%BC%8D) FULLWIDTH HYPHEN-MINUS
U+2212 −(%81%7C) −(%E2%88%92) MINUS SIGN(上記も%81%7Cとなっていることに注意)
U+2225 ∥(%81a) ∥(%E2%88%A5) PARALLEL TO
U+2016 &#8214;(%26%238214%3B) ‖(%E2%80%96) DOUBLE VERTICAL LINE
U+FF5E ~(%81%60) ~(%EF%BD%9E) FULLWIDTH TILDE
U+301C &#12316;(%26%2312316%3B) 〜(%E3%80%9C) WAVE DASH
U+FFE4 ¦(%FAU) ¦(%EF%BF%A4) FULLWIDTH BROKEN BAR
¦ U+00A6 &#166;(%26%23166%3B) ¦(%C2%A6) BROKEN BAR
U+2460 ①(%87%40) (%E2%91%A0)
U+3231 ㈱(%87%8A) ㈱(%E3%88%B1)
U+3042 あ(%82%A0) あ(%E3%81%82)
U+FF71 ア(%B1) ア(%EF%BD%B1) 半角カタカナ
U+9AD9 髙(%FB%FC) 髙(%E9%AB%99) IBM 拡張漢字(JIS 第 1〜4 水準外)
U+3402 &#13314;(%26%2313314%3B) 㐂(%E3%90%82) JIS 第 3 水準
U+5F45 彅(%FAg) 彅(%E5%BD%85) JIS 第 3 水準
U+7E6B &#32363;(%26%2332363%3B) 繫(%E7%B9%AB) JIS 第 3 水準.JIS X 0213 へ 2004 年に追加
U+845B 葛(%8A%8B) 葛(%E8%91%9B)
葛 󠄀 U+845B U+E0100 葛&#23128512;(%8A%8B%26%23917760%3B) 葛+異体字セレクタ(%E8%91%9B%F3%A0%84%80) 異体字セレクタを利用
U+30D1 パ(%83p) パ(%E3%83%91)
パ U+30CF U+309A ハ&#12442;(%83n%26%2312442%3B) ハ+半濁点(%E3%83%8F%E3%82%9A) 結合文字
😀 U+1F600 &#128512;(%26%23128512%3B) 😀(%F0%9F%98%80) サロゲートペア
𠮷 U+20BB7 &#134071;(%26%23134071%3B) 𠮷(%F0%A0%AE%B7) サロゲートペア

DBとの通信時に変換エラーが発生する

WebページがUTF-8の場合、数値文字参照ではなく文字そのものがブラウザからサーバーへ送信される。サーバーサイドではJDBCドライバーがDBのコードセットに応じて変換を行う。文字によってはSELECTのタイミングで CharConversionException(MalformedInputException) が発生する。

// スタックトレースの最後の部分のみ抜粋
Caused by: com.ibm.db2.jcc.am.SqlException: [jcc][t4][1065][12306][4.25.13] java.io.CharConversionException をキャッチしました 詳しくは添付の Throwable を参照してください ERRORCODE=-4220, SQLSTATE=null
at com.ibm.db2.jcc.am.b6.a(b6.java:794)
at com.ibm.db2.jcc.am.b6.a(b6.java:66)
// ・・・中略・・・
Caused by: java.nio.charset.MalformedInputException: Input length = 1
at java.nio.charset.CoderResult.throwException(CoderResult.java:274)
at com.ibm.db2.jcc.am.x.a(x.java:52)
at com.ibm.db2.jcc.am.bh.a(bh.java:2952)
... 50 more

-Ddb2.jcc.charsetDecoderEncoder=3というオプションを付与すると、この例外発生を回避できる。変換エラーが発生した文字は、REPLACEMENT CHARACTER(\uFFFD�)へ自動変換される

なおCENT SIGN(U+00A2)は、-Ddb2.jcc.charsetDecoderEncoder=3の設定有無に関わらず単純に文字が消える。ある文字がそれぞれの文字コードに含まれているかはこちらのサイトで確認できる(今回の場合はCENT SIGNはデータベースが利用しているcp943には含まれていないことがわかる)

U+00A2
http://www.fileformat.info/info/unicode/char/00a2/charset_support.htm

上記の表の文字(a,&,¢,¢,—,―,-,−,∥,‖,~,〜,¦,¦,①,㈱,あ,ア,髙,㐂,彅,繫,葛,葛󠄀,パ,パ,😀,𠮷)をWebページから入力し、DBへ格納して再度Webページへ表示した結果は以下の通り。

UTF-8を利用する場合、―(U+2015)などの一部の文字で文字化けが発生する。-Ddb2.jcc.ccsid943Mapping=2をJVMオプションに付与することで変換先を変更できるが、文字化けを完全に解消することはできない。Unicode上の複数のコードポイントをibm-943上では単一のコードに割り当てていることから避けることができない。WebページがShift_JISの場合に文字化けが発生していないように見えるが、前述の通り数値文字参照が利用されているためである。

ユーザーの入力 Unicodeコードポイント DBへINSERTしてSELECTした結果(WebページがShift_JISの場合) DBへINSERTしてSELECTした結果(WebページがUTF-8、-Ddb2.jcc.ccsid943Mapping=2なしの場合) DBへINSERTしてSELECTした結果(WebページがUTF-8、-Ddb2.jcc.ccsid943Mapping=2ありの場合)
a U+0061 a a a
& U+0026 & & &
¢ U+00A2 数値文字参照として扱われる 文字が消える 文字が消える
U+FFE0
U+2014 ― (HORIZONTAL BAR, U+2015)へ化ける
U+2015 — (EM DASH, U+2014)へ化ける
U+FF0D − (MINUS SIGN, U+2212)へ化ける
U+2212 - (FULLWIDTH HYPHEN-MINUS, U+FF0D)へ化ける
U+2225 ‖ (DOUBLE VERTICAL LINE, U+2016)へ化ける
U+2016 ∥ (PARALLEL TO, U+2225)へ化ける
U+FF5E 〜 (WAVE DASH, U+301C)へ化ける
U+301C ~ (FULLWIDTH TILDE, U+FF5E)へ化ける
U+FFE4 ¦(BROKEN BAR, U+00A6)へ化ける
¦ U+00A6 ¦ ¦ ¦ (FULLWIDTH BROKEN BAR, U+FFE4)へ化ける
U+2460
U+3231
U+3042
U+FF71
U+9AD9
U+3402 数値文字参照として扱われる ��(REPLACEMENT CHARACTER, U+FFFD)へ化ける ��(REPLACEMENT CHARACTER, U+FFFD)へ化ける
U+5F45
U+7E6B 数値文字参照として扱われる 繋(U+7E4B)へ化ける 繋(U+7E4B)へ化ける
U+845B 葛へ化ける 葛へ化ける
葛 󠄀 U+845B U+E0100 葛󠄀(一部が数値文字参照となる) 葛 �� へ化ける 葛 �� へ化ける
U+30D1
パ U+30CF U+309A パ(一部が数値文字参照となる) ハ �� へ化ける ハ �� へ化ける
😀 U+1F600 数値文字参照として扱われる �� へ化ける �� へ化ける
𠮷 U+20BB7 数値文字参照として扱われる � へ化ける � へ化ける

参考

5
4
0

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
5
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?