テキストファイルをオープンして内容を出力する
(この記事は Scala Advent Calendar jp 2010 : ATND の8日目です。)
「scala.io.Source.fromFile」というのがあってそれが使えそうだった。
val filename = "test.txt" scala.io.Source.fromFile(filename).getLines.foreach(println)
おおお簡単!と思ったんだけど、自動ではcloseしてくれないよね。
仕方なく自分でcloseする。
val filename = "test.txt" val source = scala.io.Source.fromFile(filename) try { source.getLines.foreach(println) } finally { source.close }
毎回これ書くのはめんどくさい。scalaが俺にユーティリティ関数を作れと囁いている。
def getLinesFromFile(filename: String, f:(String) => Unit) = { val source = scala.io.Source.fromFile(filename) try { source.getLines.foreach(f) } finally { source.close } } getLines("test.txt", println)
第一引数がファイル名、第二引数が実行させたい関数です。
で、scala.io.Sourceのソース読んだけど、FileInputStreamをラップしているような感じですね。
ただいま有志が逆引きScalaというTips集を作成しています。まだネタ不足気味なので、何かいいネタがあったら教えて下さい。
追記:こう書いた方がいいんじゃないかって話戴きました。ありがとうございます。自動的に閉じるSource - ( ꒪⌓꒪) ゆるよろ日記
- LoanPattern使って書く
- Iteratorに対して、そもそもSource自身が最後まで読んだら自動的に閉じる
■
build配下のプロジェクトクラス
import sbt._ class MyProject(info: ProjectInfo) extends DefaultProject(info) { override def libraryDependencies = Set( "net.databinder" %% "dispatch" % "0.7.7" ) ++ super.libraryDependencies }
検索するサンプル
import dispatch._ import dispatch.twitter._ import twitter.{Auth,Status} import oauth._ import oauth.OAuth._ object SearchSample { def main(args: Array[String]): Unit = { val searchWord = "rpscala" val http = new Http val tweets = http(Search(searchWord).product) val message = tweets.reverse.map { js => val Search.text(text) = js val Search.from_user(from_user) = js (Status.rebracket(text), from_user) } message.foreach({x => println(x._2 + " " + x._1)}) } }
TLを取得
import dispatch._ import dispatch.twitter._ import twitter.{Auth,Status} import oauth._ import oauth.OAuth._ import info.growl.{Growl, GrowlUtils} import java.io.File import javax.imageio.ImageIO object FriendsTimeline { val CONSUMER_KEY = "xxxxxxxxxxxxxx" val CONSUMER_SECRET = "xxxxxxxxxxxxxx" val ACCESS_TOKEN = "xxxxxxxxxxxxxx" val ACCESS_TOKEN_SECRET = "xxxxxxxxxxxxxx" def main(args: Array[String]): Unit = { val http = new Http val CONSUMER = Consumer(CONSUMER_KEY, CONSUMER_SECRET) val map = Map("oauth_token"->ACCESS_TOKEN, "oauth_token_secret"->ACCESS_TOKEN_SECRET) val token = Token.apply(map) val tweets = http(Status.friends_timeline(CONSUMER, token.get).product) val message = tweets.reverse.map { js => val Status.user.screen_name(screen_name) = js val Status.text(text) = js (Status.rebracket(text), screen_name) } // http://d.hatena.ne.jp/yuroyoro/20090724/1248431961 growl(message) } def growl(message: List[(String, String)]): Unit = { val appName = "How do you like wednesday Growl" val notificationName = "How do you like wednesday Growl" val growl:Growl = GrowlUtils.getGrowlInstance( appName ) growl.addNotification(notificationName , true) growl.register() message.foreach({ x => println(x._2 + " " + x._1) growl.sendNotification(notificationName , x._2, x._1) }) } }
Mapの初期化
var map = Map("k1"->"v1", "k2"->"v2")
ちなみに「"k1"->"v1"」の部分はタプルと言うらしい。
値の追加
map += "k3"->"v3"
取得
map.get("k1") res1: Option[java.lang.String] = Some(v1)
map.get("k1").get res2: java.lang.String = v1
map.getOrElse("k1", "not found") res3: java.lang.String = v1
map.getOrElse("k4", "not found") res4: java.lang.String = not found
Liftにライブラリを追加
project/build/LiftProject.scalaに追加
override def libraryDependencies = Set( "net.liftweb" %% "lift-webkit" % liftVersion % "compile->default", "net.liftweb" %% "lift-mapper" % liftVersion % "compile->default", "org.mortbay.jetty" % "jetty" % "6.1.22" % "test->default", "junit" % "junit" % "4.5" % "test->default", "org.scala-tools.testing" %% "specs" % "1.6.5" % "test->default", "com.h2database" % "h2" % "1.2.138", "net.databinder" %% "dispatch" % "0.7.7" ) ++ super.libraryDependencies
%と%%の違いは正直よくわかっていない。
main関数が複数ある場合
runを実行するときにどっちのmainを使うか選択肢が出る。
TODO:CustomActionsなどを使って複数のmain関数をきれいに使いこなせるようにしたい。
sbtにライブラリを追加
そもそもsbtにライブラリを追加するのがこのやり方
DefaultProjectを継承したクラスを記述して、project/build配下におけばいい。