こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

文字化け対策について

 JSPに文字コードを指定しているにも関わらず、
 「Java側でUTF-8の文字コードを指定してあげなければ、画面遷移した画面遷移先で文字化けが起こってしまう。」という状況なのですが、これの解決方法は無いものでしょうか?

【文字エンコード状況】
●JSP
 JSP側では、画面遷移元、画面遷移先の両方とも 文字コード「UTF-8で指定」しています。

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

●Java

 Java側では、
 response.setContentType("text/html; charset=UTF-8");//コンテンツタイプ
 request.setCharacterEncoding("UTF-8"); //コード変換
 
 という2点をコード変換として記述しています。


【値受け渡し状況(画面表示状況)】
●1 画面遷移元 画面1(JSP)
 <input type="text" value="あいうえお" name="name1">

●2 java(servlet)  → 画面1のname1の“あいうえお”を受取る
 String strName = new String(request.getParamete("name1"));
request.setAttribute("name", strName);
  
●3 画面遷移先 画面2(JSP) → “あいうえお”を表示
 <%= (String)request.getAttribute("name1") %>
         
 画面状況:文字化けしている。[ォ・・サウ」(といった感じです)
 

●現状の解決方法

 ここで、文字化けの解決方法として、
 画面1のリクエストをゲットする際に、
java(servlet)での、文字の受け取り方の記述を変更しました。

 String strName = new String(request.getParamete("name1"));
 
 から
 
 String struserName = new String(request.getParamete("name").getBytes("ISO-8859-1"),"UTF-8");
 
 という風に「 .getBytes("ISO-8859-1"),"UTF-8") 」 を付与してやることで、回避でききました。が、これで解決策としては妥当でしょうか?(正しいでしょうか?)
 
 気にかかっているところが、どうもこのやり方が強引に文字を変換しているようにしか思えませんでして(実際のところは正しいのかもしれませんが・・・)このまま値を渡してやっていいのか判別が付かずに困っています。
 
 この方法でも大丈夫でしょうか?
 特別、何か問題というのはありませんでしょうか?

投稿日時 - 2009-06-12 22:48:36

QNo.5039048

困ってます

質問者が選んだベストアンサー

>「これで正しいUTF-16の状態」というのは、
>ここの「 new String( bytes, "UTF-8");」で
>バイト変換した場合、"UTF-8"に文字コードセットされたデータを、
>Javaが"UTF-16"として処理出来る状態になった、ということでしょうか?

「JavaがUTF-16として処理できるようになった」のではなくて、
「UTF-8の文字が、UTF-16の文字に正しくマッピングされて、「あ」が「あ」として扱われるようになった」です。

Javaでは元の文字コードが何であろうと、文字のバイトの並びがなんであろうと、Stringは常にそのバイトの並びを、UTF-16として処理するので。

以下は変な例ですが、
正しくマッピングがされている状態とは、
元のバイトの並びがutf-8で、「0xa1、0x00」、文字としては2文字の「A、null」を意味していたときに、UTF-16でも2文字の「A、null」であるということです。
正しくないとは、これが、1文字の「A」としてだけ認識されるような状態です。
本当に変な例なので、あくまでも例として考えてください。
要するには意味が異なってしまった状態のことです。

後、2-1と、2-2は一連の流れで1セットです。紛らわしかったです。
bytes = requestParameter.getBytes("iso-8859-1");
requestParameter = new String( bytes, "UTF-8");

投稿日時 - 2009-06-27 02:37:24

お礼

ありがとうございます。
たびたびすみません(--;

「 UTF-8の文字が、UTF-16の文字に正しくマッピングされて、「あ」が「あ」として扱われるようになった 」

本当に変な例としては
utf-8の文字をutf-16にしたとき
「A、null」が「A、null」でなく「A」とだけ認識ということがあるのですね。

そこのところ不思議におもっていたところで
「utf-8なのにutf-16にして何か問題ないのだろうか」と想っていたところだったんです。

内部的な動きというものをよくわかっていないのでイメージではありますが、javaが上手いこと内部的に処理してくれてそうですね。

なんだか長い事すみません(--;
ご回答いただいた内容とても参考になりました。

投稿日時 - 2009-07-01 21:21:18

このQ&Aは役に立ちましたか?

2人が「このQ&Aが役に立った」と投票しています

回答(4)

ANo.3

>調べてみたらこれってASCIIコードのことだったのですね。
 そです。
 大抵のエンコーディングは、asciiと互換性を持たせる符号化方式をとっています。

>utf-8(最初の画面) → iso-8859-1(コンテナ通過時) → UTF16(java通過時に自動変換する) → UTF-8(javaの中で getBytes("ISO-8859-1"),"UTF-8"); として設定) → utf-8(次の画面)
>
>という流れで、
>正常に文字化けなく表示される「“あ”が表示される」、となる、ということでしょうか?

や、こんな感じだと思います。

1.HTML(UTF-8)
↓(ブラウザからコンテナが受け取るまでずっとUTF-8のバイト値)
2. Java
1) コンテナ or フィルタ
  リクエストのバイト値をiso8859-1としてJava内部コードに変換
  requestParameter = new String(bytes, "iso-8859-1");

  この時点でUTF-16になっているけれども、化け状態

2) サーブレット
  間違えた変換がされているので、
  2-1) 戻す
   bytes = requestParameter.getBytes("iso-8859-1");
  2-2) 正しく変換
   requestParameter = new String( bytes, "UTF-8");

  これで正しいUTF-16の状態

3) JSP
  JSPにかかれたものは、実行時UTF-16になる(Javaコードになるから)。ソースがShift_JISで書いてあっても、実行時にUTF-16。

  記述「<% page .... pageEncoding="UTF-8" %>」
  によって、
response.setCharacterEncoding("UTF-8");
  みたいなコードが生成され、実行される。
  <%= requestParameter %>
  みたいなのは、Javaコードとして、
  writer.print( requestParameter );
  として実行される。
  このときはUTF-16。

  先のresponse.setCharacterEncodingが指定されているので、出力が、フラッシュされるときには、UTF-16は、UTF-8に変換されてブラウザに送られる。

投稿日時 - 2009-06-18 23:06:02

お礼

ありがとうございます。

すみません、おかげさまで、
最初に比べて随分と理解ができてきました^^;


2) サーブレット
  間違えた変換がされているので、
  2-1) 戻す
   bytes = requestParameter.getBytes("iso-8859-1");
  2-2) 正しく変換
   requestParameter = new String( bytes, "UTF-8");

  これで正しいUTF-16の状態

-------------------------------------------------------------

「これで正しいUTF-16の状態」というのは、
ここの「 new String( bytes, "UTF-8");」で
バイト変換した場合、"UTF-8"に文字コードセットされたデータを、
Javaが"UTF-16"として処理出来る状態になった、ということでしょうか?

投稿日時 - 2009-06-24 19:28:03

ANo.2

>「UTF-8」であったものを「iso-2022-jp」で再度文字を変換してしまうため

すいません。間違えました、仮定する文字コードは「iso-8859-1」でした。
一から話すと、次のとおりです。

Javaの中では文字はUnicode(UTF-16)ですが、Javaの外では文字はリソースによって様々な文字コードで表現されます。
よって、外からの文字をJavaの中で同様に文字として扱えるようにするためには、その文字をUTF-16に変換する必要があるのですが、この時コンテナやフィルタで、元の文字コードを「iso-8859-1」と仮定してしまっているので、元の文字とは異なる文字に置き換えられてしまい、文字が化けることになります。

恐らくは、HTTPにリクエストパラメータの元の文字コードを指定する決められた方法が無いのでこの様になっているのではないかと思います。

>「getBytes("ISO-8859-1"),"UTF-8"); 」を付与し、コード変換する対象としては、現在文字化けが発生しているのは「日本語文字だけ」ですので、
>「日本語文字のみを対象とし、英数字については付与は不要」と考えているのですが、特に問題ありませんでしょうか?

1バイトの英数字だけなら大丈夫です。

正確に言えば、先の理屈から言えば、UTF-8とiso-8859-1とで、バイト値が変わらない文字(特に0x00~0x7f)ならどの文字も大丈夫です。
暗黙的にiso-8859-1としてUTF16に自動変換されていても元のバイト値が表す文字がUTF-8と一緒なので、結果的に同じ文字に変換してくれます。

投稿日時 - 2009-06-13 22:03:41

お礼

ありがとうございます。
文字コードについて、段々と分かってきました。

>外からの文字をJavaの中で同様に文字として扱えるようにするためには、その文字をUTF-16に変換する必要があるのですが
これに驚きました。
(無知なだけかもしれませんが^^;)

UTF-8ではなくUTF-16をJavaでは使用しているのですね。


>バイト値が変わらない文字(特に0x00~0x7f)
http://www.ie.u-ryukyu.ac.jp/~e075739/3/Report/Report/Programming1/Programming_3.pdf

調べてみたらこれってASCIIコードのことだったのですね。
>暗黙的にiso-8859-1としてUTF16に自動変換されていても元のバイト値が表す文字がUTF-8と一緒なので、結果的に同じ文字に変換してくれます。

元のバイト値が表す文字「あ」なら「あ」があったとして

utf-8(最初の画面) → iso-8859-1(コンテナ通過時) → UTF16(java通過時に自動変換する) → UTF-8(javaの中で getBytes("ISO-8859-1"),"UTF-8"); として設定) → utf-8(次の画面)

という流れで、
正常に文字化けなく表示される「“あ”が表示される」、となる、ということでしょうか?

投稿日時 - 2009-06-17 00:15:19

ANo.1

こんにちわ。

間違えてないと思います。
うろ覚えですが、サーブレットコンテナかフィルタが、リクエストパラメータの文字コードをiso-2022-jpであると仮定してUnicodeに変換するために文字化けがおきると記憶しています。
Unicodeの文字列を元のバイナリに戻して、再度コンバートするのはそのためです。
スマートではないんですが、結構一般的なやり方だと思います。

投稿日時 - 2009-06-13 15:29:35

お礼

ありがとうございます。
回答いただきました内容の方、とても助かります。

「基準なるべく基準」というものが、
ちょっとわかっていなかった矢先なので、助かりました。

>サーブレットコンテナかフィルタが、リクエストパラメータの文字コードをiso-2022-jpであると仮定してUnicodeに変換するために文字化けがおきると記憶しています。

つまり、リクエストパラメーターについては、
リクエスト時に「サーブレットコンテナ側、もしくはフィルタと呼ばれるもの」の規定?で
「UTF-8」であったものを「iso-2022-jp」で再度文字を変換してしまうため、再度「UTF-8」のコードを指定する必要がある。となる訳でしょうか?

またこれについて、
「getBytes("ISO-8859-1"),"UTF-8"); 」を付与し、コード変換する対象としては、現在文字化けが発生しているのは「日本語文字だけ」ですので、
「日本語文字のみを対象とし、英数字については付与は不要」と考えているのですが、特に問題ありませんでしょうか?

投稿日時 - 2009-06-13 19:27:27

あなたにオススメの質問