- PR -

文字化け(サーブレット)

投稿者投稿内容
T2
常連さん
会議室デビュー日: 2002/02/20
投稿数: 37
投稿日時: 2004-11-26 00:23
コンテナの設定でデフォルト文字エンコーディングを設定してしまう方法はおすすめしません。
アプリケーションのポータビリティを低下させるし、
指定するべき文字エンコーディングはアプリケーションによって異なる可能性があります。

#「おまじない」と言ってしまうことに苦言を呈するのには同意ですが。。。
takamaro
大ベテラン
会議室デビュー日: 2004/10/12
投稿数: 100
投稿日時: 2004-11-26 00:58
引用:

現在はいちいち自前で変換しなくてもAPIやサーバの環境設定などで、
文字コードを指定できるようになってきています。



現在であろうと過去であろうとサーブレットコンテナがISO 8859_1で
勝手に処理する現象に変化が起きるという訳ではないですよね。
ServletAPI 2.2準拠のコンテナが突然変異をおこすわけではないですし。
(ベンダー固有の独自処理は例外だと事前に述べてますので省略)
ServletAPI 2.3からはsetCharacterEncoding()等の国際化を意識した
新たな機能が標準で組みこまれましたが、だからといってServletAPI 2.2
環境でそれらを用いるわけにはいきません。
ですから「これは誤った方法」とかではなく、単に

1.ServletAPI 2.2 では getBytes()を用いる(基本的に)
2.ServletAPI 2.3 以降は setCharacterEncoding()等を用いる。

というだけの話しなのではないでしょうか(最期の手段でもなんでもない)
で、今回の質問では環境の提示が無い状況で話が進んでいて、バクシさんが
1の方法を提示した後に、質問者がsetCharacterEncoding()を用いて問題点
が解決したとの報告で「ああ、2の環境だったのだな」と理解し得たという流
れであったと理解しております。
では、setCharacterEncoding()を用いた手法が「正しい回答」かと考えると、
たまたまそうだっただけで、いつでもそれが正しい回答とは限りませんよね?
本来なら、一度に背景も含めて両方を説明するのが一番良いのでしょう。
私は、最もヒット率が高い(?)だろうと思われる2の方法を説明するのもあり、
最もつぶし(?)が効くだろうと思われる1を説明するのもありかな思います。
ですが、どちらも中途半端な説明であるのにも関わらず、片方の説明を揶揄する
のは如何なものかとも思います。

最期に「おまじない」について、、、
これはバクシさんご自身が釈明されればよい話しかとは思いますが、推察では
ありますが「一度に技術的内容の負担をかけては質問者が辛いだろう」という
配慮の上での発言ではなかったかと思います。
そういう判断は結構どこの技術系掲示板や書籍にも頻繁にみられる光景で、
特に問題があるものとは思えませんけどね、、setCharcterEncoding()にしても
そのメソッドのみの提示なら実質「おまじない」と大差ないわけです。
kito
ベテラン
会議室デビュー日: 2003/03/24
投稿数: 59
お住まい・勤務地: Osaka
投稿日時: 2004-11-26 02:05
引用:

takamaroさんの書き込み (2004-11-25 03:40) より:

ありませんが、遠目から眺めていた記憶が正しけば java.lang.String#getBytes() を
用いたコーディングは、ServletAPI 2.2に準拠したコンテナ環境では一般的であったと
記憶しております(各ベンダー独自の方法は別にあったにせよ)
これが、特に「誤った」と言われる程の手法ではなかったと思います。


はい、「当時は」そうでした。『「誤った」と言われる程の手法ではなかった』
さすがによくわかっていらっしゃる。過去形ですよね。

※細かいことですがTomcat3.2.xを除けば国際化機構を備えたものも少なくなかったのではと思います。
なにしろTomcatも3.3から文字エンコーディングの指定が可能になっていました。


引用:

初心者に対して「誤解を与える」とはいいますが、初心者であれ将来的に過去の遺産として
現存する「既存」のアプリケーションのメンテナンスを行なう可能性もあるわけですし、


古い環境において新しい手法が利用できないことは比較的容易に検証できるでしょう。
逆に、新しい環境において、「今となっては正しいとは言えなくなった手法」を
何も知らずに使い続けてしまうことが果たして良いことかどうか。

Servlet2.3/Tomcat4.0がリリースされてから既に3年以上経つというのに
これからServletの世界に足を踏み入れようとする若者に対して
Tomcat3.2を前提とした手法を勧めてしまうのはやはり適当でないと考えます。
Session#setAttribute()とSession#putValue()、どちらを教えますか?
kito
ベテラン
会議室デビュー日: 2003/03/24
投稿数: 59
お住まい・勤務地: Osaka
投稿日時: 2004-11-26 02:23
茶々です。

引用:

takamaroさんの書き込み (2004-11-26 00:58) より:
私は、最もヒット率が高い(?)だろうと思われる2の方法を説明するのもあり、
最もつぶし(?)が効くだろうと思われる1を説明するのもありかな思います。
ですが、どちらも中途半端な説明であるのにも関わらず、片方の説明を揶揄する
のは如何なものかとも思います。



「setCharacterEncoding()は試していませんが、getBytes()を使ったら文字化けが直りました。ありがとうございます!
これで次に進めます!ちなみにTomcat5です。環境書いてなくてすみません!」
みたいな流れになったらどうしましょ(笑)
今回は逆でよかったですね。


[ メッセージ編集済み 編集者: kito 編集日時 2004-11-26 03:00 ]
MINE
会議室デビュー日: 2003/07/02
投稿数: 17
投稿日時: 2004-11-26 11:39
引用:

T2さんの書き込み (2004-11-26 00:23) より:
コンテナの設定でデフォルト文字エンコーディングを設定してしまう方法はおすすめしません。
アプリケーションのポータビリティを低下させるし、
指定するべき文字エンコーディングはアプリケーションによって異なる可能性があります。


エンコーディングの設定は、アプリケーション毎に行うものと考えています。
逆に全アプリケーション共通の設定しかできないのであれば使えませんし・・・・

コード上でもパラメータの取得はHttpServletRequest#getParametereを
記述しているだけで、ベンダ独自の動作をするようなコードを
記述するわけでもないですし、サーバのバージョンアップなどがあっても、
変更するサーバでエンコーディングの設定ができればコードの変更は
必要ないですし、コードが単純にgetParameterで記述されているだけである分
どのような変更でもやりやすいと考えているのですが、どうでしょうか。
また、デフォルトエンコーディング設定という機能自体、それほど
固有のベンダーに依存した機能とも考えていないので、利用することに
抵抗はなかったですが・・・

[ メッセージ編集済み 編集者: MINE 編集日時 2004-11-26 11:50 ]
バクシ
会議室デビュー日: 2004/10/06
投稿数: 12
投稿日時: 2004-11-27 15:47
さまざまな方からご意見をいただき,有難うございます。
急ぎの仕事があり,今日まで眼を通すことができず,失礼しました。

「おまじない」,このようなコミュミティでは「とにかく唱えておけ」「万能薬」という響きがあるようですね。わたしはそのような意図はありませんでしたが,不適切な発言であったことは確かですので,撤回させて頂きます。申しわけありません。
「不思議な構文ですが,おまじない・・・」というのは,構文の意味を説明するのもくどくどしいので,今は理解できなくても,こう書けば文字列のエンコーディング変更ができてしまう「おまじない」です,ということを言いたかったわけです(takamaroさんの解釈のとおりです)。

さて,ある意味では問題は単純でして,takamaroさんがおっしゃるように,
1.ServletAPI 2.2 では getBytes()を用いる(基本的に)
2.ServletAPI 2.3 以降は setCharacterEncoding()等を用いる。
というのが,現時点での標準的な技法(コンテナの種類に依存しない)でしょう。

ただ,この1,2を用いて,あるいはserver.xmlなどでエンコーディングを設定する方法も含めて,「決め打ち」方式の有効性には,いまだに疑問を持っています。ここの常連方にとっては釈迦に説法でしょうが,form をのせているHTML文書のエンコーディングと,それが返すrequest parametersのエンコーディングが一致する,という前提があるからこそ,「決め打ち」でよい,ということになります。しかし,このエンコーディングの一致は保証されているわけではない,というのが,わたしが伝授された知識です。対策も考えてきました。

ここでの話題は文字化け問題ですし,kitoさんは,
>最初からデタラメな文字列が生成されない
>ようなコーディングをするべきでしょう。
と言われるわけです。ここで「決め打ち」の有効性についての意見が出てくるであろうと期待するのは,わたしのように古い人間だけかもしれません。
最近のサーブレットの世界では「決め打ち」で良い,他のことはごちゃごちゃと考えるな,というのが常識なのでしょうか?

対策とは下記のようなものです。ネゴシエーション方式とでも言いましょうか(Shift-JISの多様さに起因する問題は無視します)。

0.サーブレットコンテナには,requestのエンコーディングを判定する手段がないのだから,とりあえず"ISO-8859-1"としてデコードさせる(実は何でもよいが,これがデフォルトの動作であるばあいが多い)。
1.request parameterとして,かならず特定の文字(とりあえず漢字の”一”)が返るようにしておく(<input type="hidden" name="nego" value="一">)
2.それによって相手のエンコーディングを判定する(日本語のみならずGBやBig5まで判定できる)
3.同じセッションのなかで受けとるparametersは,判定されたエンコーディングにもとづきgetBytes()で変換する。

これも時代遅れの腐った技法なのでしょうか?
JavaにはgetBytes()が用意されているので,「国際化」も「文字化け追放」も容易に実現できる(素晴らしい!),というのがわたしの考えなのです。




[ メッセージ編集済み 編集者: バクシ 編集日時 2004-11-27 20:14 ]
kito
ベテラン
会議室デビュー日: 2003/03/24
投稿数: 59
お住まい・勤務地: Osaka
投稿日時: 2004-11-27 18:56
引用:

バクシさんの書き込み (2004-11-27 15:47) より:

>最初からデタラメな文字列が生成されない
>ようなコーディングをするべきでしょう。
と言われるわけです。ここで「決め打ち」の有効性についての意見が出てくるであろうと期待するのは,わたしのように古い人間だけかもしれません。



単にそういう話の流れでなかっただけでしょう。
話が全く違う方向に向かってますけど、このままここで続けるんですか?

このスレッドの質問に対しては、最初の30分で答えが出ていますし、
そもそも論なら『Web/Servletにおける文字コード決め打ちの有効性について』のようなサブジェクトで新しくスレッドを立てた方が良いような気がします。


[ メッセージ編集済み 編集者: kito 編集日時 2004-11-27 19:19 ]

スキルアップ/キャリアアップ(JOB@IT)