scala勉強会8回 のこととか

またもやscala勉強会(今度は8回)がネタ元です。

この前と大体同じようなことしてみようかとおもいます。



元コード

まず、家で実行しようとしたら、エラー起きて実行できないというトラブル発生(´;ω;`)
エラー内容

Exception in thread "main" java.nio.charset.UnmappableCharacterException: Input length = 2
	at java.nio.charset.CoderResult.throwException(CoderResult.java:261)
	at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:319)
	at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:158)
	at java.io.InputStreamReader.read(InputStreamReader.java:167)
	at java.io.BufferedReader.fill(BufferedReader.java:136)
	at java.io.BufferedReader.read(BufferedReader.java:157)
	at scala.io.BufferedSource$$anonfun$1$$anonfun$apply$mcI$sp$1.apply$mcI$sp(BufferedSource.scala:28)
	at scala.io.Codec.wrap(Codec.scala:63)
	at scala.io.BufferedSource$$anonfun$1.apply(BufferedSource.scala:28)
	at scala.io.BufferedSource$$anonfun$1.apply(BufferedSource.scala:28)
	at scala.collection.Iterator$$anon$13.next(Iterator.scala:149)
	at scala.collection.Iterator$$anon$24.hasNext(Iterator.scala:484)
	at scala.collection.Iterator$$anon$19.hasNext(Iterator.scala:368)
	at scala.io.Source.hasNext(Source.scala:236)
	at scala.collection.Iterator$class.foreach(Iterator.scala:631)
	at scala.io.Source.foreach(Source.scala:179)
	at scala.collection.TraversableOnce$class.addString(TraversableOnce.scala:502)
	at scala.io.Source.addString(Source.scala:179)
	at scala.collection.TraversableOnce$class.mkString(TraversableOnce.scala:467)
	at scala.io.Source.mkString(Source.scala:179)
	at scala.collection.TraversableOnce$class.mkString(TraversableOnce.scala:478)
	at scala.io.Source.mkString(Source.scala:179)
	at scala.collection.TraversableOnce$class.mkString(TraversableOnce.scala:485)
	at scala.io.Source.mkString(Source.scala:179)
    at Reflexa$.getXMLSource(Reflexa.scala:20)
・・・

UnmappableCharacterExceptionググると、

入力文字 (またはバイト) シーケンスは有効だが出力バイト (または文字) シーケンスにマップできない場合にスローされるチェックされる例外です。

だそうです。
そもそもREPLに貼りつけてやろうとしたんですが、その時点で警告出てました

warning: there were deprecation warnings; re-run with -deprecation for details

しかしなぜかれっぷるさんが、デフォルトだと警告内容表示してくれないので、

scala -deprecation

っていうように、警告を表示するように、オブション追加して起動しましょう*1
警告内容↓

warning: method encode in object URLEncoder is deprecated: see corresponding Javadoc for more information.
 search_words.map(URLEncoder.encode).mkString("%20")

つまり
URLEncoderのencodeってメソッド使わんほうがいいよ(´Д`)
っていう話です。使わんほうがいい理由はこちら
単にエンコードを明示的に指定しろって話です

この警告が、さっきのエラーとも関連ありそうかと思いきや、Source.mkStringでエラー起きてるんで違いますね。

同じエンコードの指定の問題ですが。

予想として、XMLで取得したはずのデータをstringに変換しようした時点でエラーってことは、取得するときのエンコードがちがうってことなので

        val src = Source.fromURL(url + "?q=" + query + "&format=xml")

        val src = Source.fromURL(url + "?q=" + query + "&format=xml","UTF-8")

にしたら解決しました。こういう場合のメソッドの使い方を調べ方としてはREPL使って、実際に試すのが一番早いです
以下REPLの出力そのまま貼りつけ

scala> scala.io.Source.

DefaultBufSize         asInstanceOf           createBufferedSource   fromBytes              fromChar
fromChars              fromFile               fromInputStream        fromIterable           fromRawBytes
fromString             fromURI                fromURL                isInstanceOf           stdin
toString

scala> scala.io.Source.fromURL


def fromURL(s: String)(implicit codec: Codec): BufferedSource
def fromURL(s: String, enc: String): BufferedSource
def fromURL(url: java.net.URL)(implicit codec: Codec): BufferedSource
def fromURL(url: java.net.URL, enc: String): BufferedSource

scala> scala.io.Source.fromURL

Sourceにどんなメソッドがあるか知りたかったら、scala.io.Source.まで打ってtabキー押すと上記のように、メソッド一覧が表示されます。
さらに詳しく知りたい場合、scala.io.Source.fromURLまで打って*2またもやtabキーを押せば、
引数と戻り値が表示されるので、たいていはこれ見れば(ドキュメント見るまでもなく)使い方分かります。それでもわからなかったら、実際使ってみたほうがはやいです。

このfromURLの場合は、暗黙引数でCodecっていう文字コード指定するオブジェクトを勝手にとってくれるみたいですが、その暗黙引数が間違ってたってことですね。なので明示的に指定しましょう


しかしそもそも返されるデータには

<?xml version="1.0" encoding="UTF-8" ?>

っていうXML宣言ついてるんで、どうにかすれば、指定しなくて済むかも?
と考えたところで、時間なくなったんで、かなり中途半端ですが、ここで一旦終わり(´・ω・`)
続きはまた後で書きます。 → 書きました

ソースコードいじる記事書くつもりが、単にエラーの原因究明の仕方と、REPLの使い方講座になってしまった・・・・(´・ω・`)

*1:自分はその他にも、毎回色々オブションとか読み込むスクリプト指定するので、REPL起動させるバッチファイルつくってあります

*2:scala.io.Source.までの入力保持されるんで実際入力するのは"fromURL"だけですけど