第45回
■
■SqueakではじめるSmalltalk入門 第45回
■
本連載では、名前は知っていてもなかなか触れる機会のないSmalltalkについて、最近話題のSqueakシステムを使って紹介しています。今回は、第12回で取りあげた日本語ファイルストリームの扱いを復習しながら、ファイルリストが文字化けを起こす原因を考え、その元凶となるメソッドをSmalltalkシステムならではの便利機能を用いて突き止めてみます。
▼文字化けを故意に起こしてみる
日本語ファイルは、そこで使われる文字コードにマッチしたコンバータオブジェクトを介在させることで、はじめて正しく読み書きできる…ということは第12回で説明したとおりです。つまり、文字化けは、コンバータの不一致により引き起こされるわけです。これは簡単に試すことができます。
まず、新しいワークスペースを開き(デスクトップメニューから「開く…」→「ワークスペース」)、次のスクリプトをコピー&ペーストした後、あらためて全体を選択し、print it(黄ボタンメニューから「式を表示」もしくはcmd+P)してみてください。ここでShiftJisExample.txtには、第12回でシフトJISコードの日本語文字列を収めたファイルをそのまま利用しています。該当するものがなければ、適当なエディタで同名ファイルを作ってNihongoSqueak7フォルダにあらかじめ入れておく必要があります。
| file |
file _ FileStream fileNamed: 'ShiftJisExample.txt'.
file converter: ShiftJISTextConverter new.
^ {file converter. file contents}
" => #(a ShiftJISTextConverter 'シフトJISの日本語文字列') "
返値の配列の第1要素はコンバータ、第2要素は読みとったファイルの内容を表わしています。ファイルに使われている文字コードがコンバータのそれと一致しているため、文字化けせずに読めるはずです。
ではコンバータをわざと別のものに変えてみましょう。
| file |
file _ FileStream fileNamed: 'ShiftJisExample.txt'.
file converter: Latin1TextConverter new.
^ {file converter. file contents}
配信されるメールに不都合があるといけないので、結果はここには示しませんが、注文通り文字化けするはずです。ファイルリストにおける文字化けもこれと同じで、内容を表示する際に用いられたファイルストリームのコンバータが正しくシフトJISのものになっていなかったのが原因だと推察できます(簡単のため、そういうことにしておいてください…)。
▼edit送信時の文字化けはコンバータの設定とは無関係
では、editメッセージを送る前に、正しいコンバータを指定していないのが原因か…というとそうでもないようです。次のスクリプトをdo itしてみてください。
| file |
file _ FileStream fileNamed: 'ShiftJisExample.txt'.
file converter: ShiftJISTextConverter new.
file edit
変わらず文字化けしたままですね。どうやらファイルリストは、あらかじめ設定されたコンバータは使わずに、独自のコンバータの設定でファイルストリームの読み取りをしているように見受けられます。
▼FileListはどんなコンバータ設定をしているのかを調べる
コンバータの設定には#converter:を使うので、FileListの中で#converter:を起動するためのメッセージ送信を行なっている箇所を突き止めれば、どんなコンバータを割り当てているのかを調べることはできそうです。じつはSmalltalkでは、あるメソッドを起動するためのメッセージ送信がどのクラスのどのメソッドで行なわれているのかについて、ほぼすべてをシステムが把握しているので、こうしたことは簡単に調査できます。
先ほどのスクリプト中の「converter:」をダブルクリックするなどして選択し「senders of it」(そのメソッドを起動するためのメッセージの送信元)を意味するcmd+Nをタイプします。すると#converter:を起動するためのメッセージ式を含むメソッドの一覧が作られ、その各々の定義を見ることができる特殊なブラウザが画面に現われます。
[fig.A]#converter:を起動するためのメッセージを含む全メソッド
上のペインのリスト中、FileListに定義されているメソッド群に注目しましょう。これらの中で、文字コードを明示的に指定していなさそうなのは、名前と定義内容から#readContentsBrief:だけだと分かります(簡単のため、そういうことにしておいてください…)。
▼注目メソッドに“印”を付けて、その起動を確認する
ここで、ちょっとイタズラをして、ファイルリストがファイルの内容を表示するとき実際に、このメソッドを起動しているかどうかを確認してみましょう。
#readContentsBrief:の定義中どこでもいいのですが、テンポラリ変数の宣言の後にちょうど一行空いているので、そこに次の式を追加します。
'bingo!' displayAt: 0 @ 0.
この式は、読んで字の通り、「bingo!」という文字列をビットマップとして画面左上に表示するためのものです。コピーして、ブラウザの該当個所にペーストしたら、コンパイルのため、accept(黄ボタンメニューの「了解」もしくはcmd+S)します。イニシャルを尋ねられたら、適当にタイプしてこれもacceptします。ここで設定したイニシャルはUtilities setAuthorInitialsをdo itすることで、後からいつでも変更可能ですので、本当に適当なもので構いません。
無事、コンパイルが終わると(Smalltalk ではコンパイルはメソッド単位で行なわれます)、次からこのメソッドが起動するたびに画面の左上にbingo!という文字が現われるようになります。C言語のprintfデバッグにちょっと似ていなくもありませんね。
実際に、エディタモードのファイルリストを開いてみます。
(FileStream fileNamed: 'ShiftJisExample.txt') edit
いかがでしょう。画面左上にbingo!の文字は現われましたか? まさにビンゴ。かなりアバウトな探し方でしたが、どうやらこの#readContentsBrief:メソッドで当たりのようです。そうすると、
f converter: (self defaultEncoderFor: self fullName).
としているところで、正しいコンバータを指定してやれば文字化けは解消できる、ということになります。
どうやら問題の核心に近づくことができたようですが、字数のほうがかなりオーバー気味なので、この続きは次回。
このページを編集 (5274 bytes)
|
以下の 1 ページから参照されています。 |
This page has been visited 878 times.