- PR -

Windows上でlog4jを使用した所UTF-8で出力されない

投稿者投稿内容
マーサ
ベテラン
会議室デビュー日: 2004/11/26
投稿数: 87
投稿日時: 2004-11-26 22:02
始めまして、マーサと申します。

Windows上でlog4jを使用してロギングを行っているのですが、エンコーディングにUTF-8を指定しても
SHIFT-JISで出力されているみたいです。

Windowsの環境だとUTF-8で出力したいのですが、出来ないのでしょうか?
やり方がいけないのか、出来ないのか困ってしまってます。

どなたか知っている方がいらっしゃいましたら、ご教授願います。


以下がエンコーディングを指定している部分です。
**********
// rootLoggerオブジェクトの取得
Logger RootLogger = Logger.getLogger(S_ROOT);
// Appenderの設定をクリア。外部ファイルでの設定をクリアする。
RootLogger.removeAllAppenders();
// log出力レベルを設定
RootLogger.setLevel(m_logLevel);
// LayoutManager生成
Layout layout1 = new PatternLayout("%d [%t] %-2p> %c: %m%n");

// アペンダ作成
RollingFileAppender rfa = null;
// アペンダ生成
rfa = new RollingFileAppender(layout1, logFileName, true);
// 最大ファイルサイズ指定
rfa.setMaximumFileSize(m_maxFileSize);
// 最大バックアップファイル数指定
rfa.setMaxBackupIndex(m_maxBackupCnt);
// エンコーディング指定
rfa.setEncoding("UTF-8");
**********

動作環境:
WindowsXP Professional
log4j 1.2.8
JDK 1.4.2-06
JBuilder 8(開発&動作確認)

以上、宜しくお願い致します。

[ メッセージ編集済み 編集者: マーサ 編集日時 2004-11-26 22:27 ]
takamaro
大ベテラン
会議室デビュー日: 2004/10/12
投稿数: 100
投稿日時: 2004-11-27 03:21
わたしはlog4jを検証する環境も、使った経験もないのですが、多少気になったので
Webにあるドキュメントを見てみたのですが、、、

http://www.jdocs.com/log4j/1.2.8/api/org/apache/log4j/WriterAppender.html

setEncoding() の処に「No description available」と書かれてました。
わたしの悪い予感が正しければ「こりゃ、なーんも実装なんぞしておらんぞぃ」
という事ではないでしょうか(事実なら理解に苦しみますがw
それとも、最新のバージョン(v1.2.9?)では実装されているのでしょうかね?
v1.2.9のドキュメントには「No description available」が消え「  」に
なってましたけど、、、w

で、対策としては設定ファイルのエンコード属性に文字コードを記述するか、
org.apache.log4.WriterAppender#setWriter() で直接ファイルへのストリーム
を渡してやるといった方法が考えられそうです。
前者も後者も検証環境がないわたしには試す術がありませんが、提案という事で。

引用:

FileOutputStream fos=new FileOutputStream(logFileName);
OutputStreamWriter writer=new OutputStreamWriter(fos,"UTF-8");
rfa.setWriter(writer);



後者がこれで上手く動けば良いんですが、、かなり怪しい気も、、w
特に実際に使用するクラスがRollingFileAppenderですし。。。
takamaro
大ベテラン
会議室デビュー日: 2004/10/12
投稿数: 100
投稿日時: 2004-11-27 03:27
あちゃちゃ、、、QUOTEじゃなくCODEでしたね。失礼。

コード:

FileOutputStream fos=new FileOutputStream(logFileName); 
OutputStreamWriter writer=new OutputStreamWriter(fos,"UTF-8"); 
rfa.setWriter(writer);

マーサ
ベテラン
会議室デビュー日: 2004/11/26
投稿数: 87
投稿日時: 2004-11-27 11:47
takamaroさん、返答有難う御座います。

確かにsetEncoding()は利用出来ないみたいです。。。
1.2.9でも試してみたのですが、同様な結果となりました。

以下のコードを試して見ました。

引用:


FileOutputStream fos=new FileOutputStream(logFileName);
OutputStreamWriter writer=new OutputStreamWriter(fos,"UTF-8");
rfa.setWriter(writer);



はい、これでUTF-8で書かれています。
しかしログがクリアされてしまうので、使用はちょっと難しいかな。。。
バックアップ等はlog4j任せなので、その機能が使えなくなるとlog4jを使う意味も無くなってしまいます(>_<)
これで、ログがクリアされない方法がわかればこの方法で行こうと思います。


しかし何故setEncodingが出来ないのやら・・・。
マーサ
ベテラン
会議室デビュー日: 2004/11/26
投稿数: 87
投稿日時: 2004-11-27 11:58
引用:


FileOutputStream fos=new FileOutputStream(logFileName);
OutputStreamWriter writer=new OutputStreamWriter(fos,"UTF-8");
rfa.setWriter(writer);

はい、これでUTF-8で書かれています。
しかしログがクリアされてしまうので、使用はちょっと難しいかな。。。
バックアップ等はlog4j任せなので、その機能が使えなくなるとlog4jを使う意味も無くなってしまいます(>_<)
これで、ログがクリアされない方法がわかればこの方法で行こうと思います。



自己レスです。。。
早とちりしてしまった><
追加で書き込み出来ますね。

コード:

FileOutputStream fos=new FileOutputStream(logFileName, true); 



これで、大丈夫そうです。
後は、バックアップ等確認して動作すればOKです。

有難う御座いました。m(__)m
マーサ
ベテラン
会議室デビュー日: 2004/11/26
投稿数: 87
投稿日時: 2004-11-27 18:51
え〜、追加報告です。

OutputStreamWriterを作成しログの出力に成功しましたが、
ファイルのローリングが出来ないみたいです。
確認した内容は、log4j標準とOutputStreamWriterを作成したものを、
それぞれ1Mでバックアップを取るように設定し同時に実行させてみました。

log4j標準の方は約1Mでバックアップが作成されました。
作成した方は1Mを超えてもバックアップが作成されませんでした。

現状のlog4jはカスタマイズして使おうと思うと、色々と問題が出てくる見たいですね。。。

PS
エンコーディングの件ですが、現状OS依存らしいです。
takamaro
大ベテラン
会議室デビュー日: 2004/10/12
投稿数: 100
投稿日時: 2004-11-28 04:17
大雑把にですけどLog4J1.2.8のソースを拾ってきてAppender系列のみを
ざーっと眺めてみました(飛ばし読みですので誤読の際はご容赦を)

RollFileAppenderクラスの場合、org.apache.log4j.helper.CountingQuiteWriter
クラスを用いるようです。
しかし指定のファイル容量に達すると、新たなファイル出力ストリームを生成し直す
必要が出てきますので、setWriter()でCountingQuiteWriterインスタンスを渡した
ところで要件は満たせそうにないですね。
RollingFileAppenderの大雑把な処理の流れは、、、


1.subAppend()に引数LoggingEventが渡され呼び出されログの書きこみが行なわれる(通常)
2.指定のファイルサイズを超えた場合、rollOver()メソッドが呼び出される
3.各ファイルの置き換えが行なわれ、新たなファイルへのストリームを生成する為に
 setFile()が呼び出される
4.そこで生成されたストリームに対し、1.の処理が繰返される

といった感じのようです。
で、今回の焦点はストリームですのでsetFile()の処理の中身が問題になるわけですが、
見てみると生成部分はsuper.setFile()で親クラスFileAppenderのsetFile()が呼ばれ、

Writer fw = createWriter(new FileOutputStream(fileName, append));

と、FileAppenderの親クラスWriterAppenderのcreateWriter()メソッドが呼ばれてます。
で、驚いた事にcreateWriter()では、

String enc = getEncoding();
     ・
     ・
retval = new OutputStreamWriter(os, enc);

と、OutputStreamWriter作成時にエンコード指定されているんですよね。
だとしたら何でsetEncoding()で指定しても希望通りの処理がなされないのか??(うーん
ここでストリームの作成に失敗していると思われるのですが、その場合

LogLog.warn("Error initializing output writer.");
LogLog.warn("Unsupported encoding?");

と処理が続き、失敗時にはエラーがログに書きこまれるはずですので一応調べて見て下さい。
*もしかすると、わたしが見ているソースとビルドされたものとは違うのでしょうかね?
だとすると、このソースからパッケージを作れば上手くいくのかしら。。。

気を取り直して(笑)続けると、この後、RollingFileAdapterがオーバーライドした
setQWForFiles()メソッドに、先ほど作成されたストリームが引数で渡され、その引数
をもとに、最初に述べたCountingQuiteWriterを拡張し、ログ書きこみに用いられると
いった流れのようです。

あー、長々とすいませんw
結局「問題がありゃー、継承でもして上書きすればいい」と思ってたんですが、問題点
が解からず仕舞いで何もできませんでした。ってとこです。すみません。

と、ここまで書いていて1つ「もしかして、、」が思い浮かびました(汗
RollingFileAppenderのインスタンスを生成する時点でデフォで作られてしまう
ストリームがsetEncoding()指定よりも先なのが、問題だったりしませんかね?
要するに、最初に作られるCountingQuiteWriterはエンコード文字指定前のものです
から、OS依存の文字コードで処理されてしまうのではないかと、、、
そうだとしたら、消せば良いんですよね、、、reset(),closeFile()....
どれを使えば良いか、ちと直ぐには分かりませんが、二度目の提案という事でw

P.S 駄目でしたら、次回はもう少し真面目にソース読みますんで。
takamaro
大ベテラン
会議室デビュー日: 2004/10/12
投稿数: 100
投稿日時: 2004-11-28 04:57
先ほどは「最初のストリームを消せば良い」って書きましたが、
考えてみれば無駄な処理ですよね。作って、消してって。
もし、RollingFileAppenderを拡張したクラスの使用が可能ならば

コード:


public class EncodeableRollingFileAppender extends RollingFileAppender{
public EncodeableRollingFileAppender(Layout layout,String filename,
boolean append,boolean bufferedIO, String enc) throws IOException{
setEncoding( enc );
this.layout=layout;
this.setFile(filename, append, bufferedIO);
}
}



こんな風にコンストラクタで指定してあげれば良さそうですね。

[ メッセージ編集済み 編集者: takamaro 編集日時 2004-11-28 05:09 ]

[ メッセージ編集済み 編集者: takamaro 編集日時 2004-11-28 05:14 ]

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