QA@IT

ScalaでRTFを読む

2469 PV

ScalaでRTFを読みたいのですがどのような方法が考えられるでしょうか?RTFは例えば次のようなものです.

{\rtf1\ansi\ansicpg932\uc1 {\fonttbl\f0\fnil\fcharset222 \'41\'6E\'67\'73\'61\'6E\'61\'4E\'65\'77;\f1\fnil\fcharset128 \'41\'72\'69\'61\'6C\'4D\'54;\f2\fnil\fcharset222 \'41\'6E\'67\'73\'61\'6E\'61\'4E\'65\'77\'2D\'42\'6F\'6C\'64;}\pard\plain\ql\f0\fs20 {\fs22 \u3648 \'E0\u3619 \'C3\u3634 \'D2\u3651 \'E3\u3594 \'AA\u3657 \'E9\u3626 \'CA\u3633 \'D1\u3597 \'AD\u3621 \'C5\u3633 \'D1\u3585 \'A1\u3625 \'C9\u3603 \'B3\u3660 \'EC\u3649 \'E1\u3621 \'C5\u3632 \'D0\u3619 \'C3\u3641 \'D9\u3611 \'BB\u3649 \'E1\u3610 \'BA\u3610 \'BA\u3605 \'B5\u3656 \'E8\u3629 \'CD\u3652 \'E4\u3611 \'BB\u3609 \'B9\u3637 \'D5\u3657 \'E9\u3651 \'E3\u3609 \'B9\u3588 \'A4\u3641 \'D9\u3656 \'E8\u3617 \'C1\u3639 \'D7\u3629 \'CD\u3612 \'BC\u3641 \'D9\u3657 \'E9\u3651 \'E3\u3594 \'AA\u3657 \'E9\u3609 \'B9\u3637 \'D5\u3657 \'E9}{\f1\fs22 \'3A\par }{\b\f2\fs22 \u3588 \'A4\u3635 \'D3\u3648 \'E0\u3605 \'B5\u3639 \'D7\u3629 \'CD\u3609 \'B9\par }{\fs22 \u3588 \'A4\u3635 \'D3\u3648 \'E0\u3605 \'B5\u3639 \'D7\u3629 \'CD\u3609 \'B9\'20\u3610 \'BA\u3656 \'E8\u3591 \'A7\u3594 \'AA\u3637 \'D5\u3657
...
\'D2\u3604 \'B4\u3648 \'E0\u3592 \'A8\u3655 \'E7\u3610 \'BA\u3619 \'C3\u3657 \'E9\u3634 \'D2\u3618 \'C2\u3649 \'E1\u3619 \'C3\u3591 \'A7\u3652 \'E4\u3604 \'B4\u3657 \'E9}}

WEB上でいろいろ当たりましたが、

import scala.io.Source
val filename = "sample.txt"
for (line <- Source.fromFile(filename).getLines()) {
  println(line)
}

のような行単位処理のものばかりです.RTFなのでまず行はなく、スペースやバックスラッシュを区切りにトークンを切り出して、順に読んでゆくという感じになると思うのですが???

以上 初心者の質問ですみませんがよろしくお願いいたします.

回答

自己RESです.

WEB上でいろいろ当たりましたが、
のような行単位処理のものばかりです.

以下のようにすれば1文字づつ取り出してファイル全体を表示できました.

import scala.io.Source
object fileIoTest {
  def main(args: Array[String]): Unit = {
    val source: Source = Source.fromFile(args(0))
    recurse(source)
  }
  def getChar(src:Source): Option[Char]={
    if (src.hasNext)
      Some(src.next)
    else
      None
  }
  def recurse(source: Source): Unit={
    getChar(source) match{
      case Some(s) => print(s);recurse(source);
      case None => ;
    }
  }
}

しかしこれで解析するのはどうもイマイチに見えます.以下のようなパーサーコンビネータを作ってみたらとりあえずはパースを通りました.やりたいのはテキスト抽出なので、こちらで挑戦してみます.

class RtfParser extends RegexParsers{
  def text: Parser[Any] = "[0-9a-zA-Z.-;]+".r
  def asciiLetterSequence: Parser[Any] = "[a-z]+".r
  def controlWord: Parser[Any] = "\\"~asciiLetterSequence~delimiter
  def delimiter: Parser[Any] = "[\t\n ]*".r|"[-]?[0-9]+".r
  def controlSymbol: Parser[Any] = "\\"~"['*]".r~"[0-9a-zA-Z]*".r
  def group: Parser[Any] = "{"~rep(controlWord|controlSymbol|text|group)~"}"
}

以上

編集 履歴 (0)
ウォッチ

この質問への回答やコメントをメールでお知らせします。