またもや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の使い方講座になってしまった・・・・(´・ω・`)