uehaj's blog

Grな日々 - GroovyとかGrailsとかElmとかRustとかHaskellとかReactとかFregeとかJavaとか -

groovyでスクリプトのエンコーディングを指定する

前に、「コメントに何を書いてもいい」と思うのは、/**/については正しいが、//については正しくない」という記事を書きましたが、そこでの対策との一つとしては、「スクリプトのエンコーディングを正しく指定する」でした。

で、続編として「Groovyでスクリプトのエンコーディングを設定する方法」について調べてみましたので書いてみます。嘘があったら済みません。コメント欄などでご指摘ください。

まず、対処の方向性としては2つ3つがあって、つまり

であります。なお、(1)をしてよいのであれば、(2)の設定は(1)を引き継ぎます(2)の設定は、SimpleTemplateやTemplateServlet(GSPみたいなもの)エンコーディング以外については、(1)を引き継ぐので、SimpleTemplate/TemplateServletを使わない場合は、(1)だけで十分です。使う場合(例えばGaelykを使う場合)は(1)(2)の両方を設定しておくと良いようです。

システムプロパティの設定方法としては、

  • (a)Java環境全体への設定として、_JAVA_OPTIONSという環境変数で-Dxxx=yyyのように設定する
  • (b)Groovyの設定として、JAVA_OPTSという環境変数に-Dxxx=yyyのように設定する
  • (c)GAEアプリの場合、appengine-web.xmlで設定する。

という2つ3つの方法があります。JAVA_OPTSを読み取っているのは<GROOVY_HOME>/bin/startGroovy(.bat)です。

ところで、今のこの日本において、Java環境のデフォルトエンコーディングを変えたくなるのは、デフォルトエンコーディングShift_JIS系のWindowsのJava環境とMacのJDK6以降であり、かつ、実際に変えたいのは、UTF8にしたいという話ですよね。と、決めつける。

まとめ

まとめに入ります。以下に対処案を示します。すべてBashの記法です。

案1

なるべく限定的に、Groovyスクリプトのソースコードの問題だけを対処したいなら、

export JAVA_OPTS='-Dgroovy.source.encoding=UTF-8'

とする。この場合、デフォルトエンコーディングに変更は無い。つまり、デフォルトエンコーディングがSJISである場合、上記を行えばUTF8で書かれたGroovyコードを文字化け無く読み取って実行できるが、この中で例えば(UTF8で)書かれた「pritln "ほげ"」とかいうコードで出力される文字列は、デフォルトエンコーディング(SJIS)に従うし、File#eachLine()で読み取る文字列もSJISであることが期待され、他の文字コードなら化ける。簡単な回避策は無い。

案2

SJISとは手を切りたく、ソースコードも出力もUTF-8にしたい場合で、ただしJava環境全体に影響は与えたくはなくて、Groovy限定で良い場合。

export JAVA_OPTS='-Dfile.encoding=UTF-8'

この環境変数はstartGroovyが読み取るものなので、Groovy以外には影響を与えません。とはいえ、他のツールで使っている環境変数名と偶然一致しているという可能性はありますね。

案3

Groovyに限定せず、Java全体に関してデフォルトエンコーディングを全てUTF-8に変更したい場合。根源的対策*1

export _JAVA_OPTIONS=-Dfile.encoding=UTF-8

しかし、この場合、1点問題があって、Macだけかもしれせんが、JVM起動のたびに1行よけいなエラーメッセージ「Picked up _JAVA_OPTIONS: ..」とかいうのが標準エラー出力に出てきます。はなはだしくウザく、回避策は不明です。

案4
alias groovy='groovy -Dfile.encoding=UTF-8'
alias java='java -Dfile.encoding=UTF-8'
alias javac='javac -J-Dfile.encoding=UTF-8'

とか。

なぜこんなことをぐだぐだとわざわざ書いてるのか?

Javaの場合、直接Javaコマンドでプログラムを起動することが少なく、バッチファイルやシェルスクリプトで起動するwrapperを経由することが多いので、エンコーディングはそれらのスクリプト中で明示的に-D=file.encoding=UTF8オプションがつければ良い話です(ついてなければスクリプトを書き換えてつける)。あるいはIDEの設定で済む話です。

しかし、Groovyの場合、書き捨ての小さなスクリプトなどを「頻繁に」かつ、「コマンドラインから」、「groovyコマンドから直接」実行する使い方をしたくなるときが多くあり、困るのですよ。

まとめ

ちなみに私としては案1+案2で

export JAVA_OPTS='-Dgroovy.source.encoding=UTF-8 -Dfile.encoding=UTF-8'

こんな風にしてます。file.encodingだけではなくgroovy.source.encodeingも指定しているのは何となく念のためです。(追記: 山本さんの指摘によれば、Gaelykなどではこの対処はビンゴ。テンプレートを扱う場合などは、両方を設定した方がいいときがあるようです。)

*1:ただし、以下は以下を実行したシェルとその子プロセスにしか影響を与えないので注意。GUIとかIDEから起動した場合にも効力を発揮したい場合は違う設定方法となるでしょう。

JGGUGサマーイベントのお知らせ

以下にありますように、今週末の土曜日にJGGUGイベントが実施されます。
http://www.jggug.org/news/summer_event_2009

8月22日(土)、IBM渋谷オフィスにて、JGGUGの定例イベント g* ワークショップの
サマースペシャルバージョンを開催します。ふるってご参加下さい。

        • -

日時: 2009年8月22日(土) 14:00〜18:00頃 (終了後、懇親会開催予定)
場所: IBM渋谷オフィス
東京渋谷区道玄坂一丁目12-1 マークシティウェスト18階
費用: 無料
持ち物: 特になし (ノートPC推奨。無線LANと電源が利用できます)
定員: 40名
申し込み: 事前の参加登録が必要です。こちらのフォームにご記入下さい:
当日連絡先: 090-6486-7624 (山田携帯電話)

アジェンダ:
※現在計画中のためセッションの追加・変更がある場合があります。
1.イントロダクション
参加メンバ全員による自己紹介、Groovy/Grailsへの取り組み・期待など
の短いトークセッション。
2.実践Groovyプログラミング
コーディネータ: 上原さん、須江さん、(追記)関谷さん
実践的なお題をベースにした初中級向け参加型プログラミングチャレンジ。
3.ライブ開発 Groovy/Grails/Gaelyk on GAE/J
コーディネータ: 山本さん
g*なアプリをライブ開発し、GAEクラウド上のg*なフレームワーク
展開していきます。PCがあれば一緒に手順を追いながら体験することも。

今回は「サマースペシャル」として、いつもの平日ではなく土曜の午後に
長めの時間をとって、より双方向で参加型のワークショップを計画して
います。ノートPCを持参してふるってご参加ください。「夏祭り」らしく
ノベルティグッズやプレゼントも用意する予定です。お楽しみに!

なかなか他では手に入らぬものがもらえるようですよ。

わたしも「実践Groovyプログラミング」のコーナーでは、コーディネーターの方をさせていただきます。よろしくお願い致します。

濃い話薄い話などしたいかたは是非どうぞ!