tailの実装
Posted feedbacks - Scala
オプションの処理にかなり場所をとられてしまっていますが...。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | import java.io.FileNotFoundException
import java.io.File
import java.io.FileInputStream
import scala.collection.mutable.HashMap
class InvalidArgumentException extends Exception {}
class GetOpt(f:String) {
var _params:List[Tuple2[String,Boolean]] = null
var _opt:HashMap[Any,Any] = null
var _rest:Array[String] = null
_params = f.toList.foldLeft(List[Tuple2[String,Boolean]]()) { (l,c) =>
c match {
case ':' => l match {
case List() => throw new InvalidArgumentException
case h::r => (h._1,true)::r
}
case k => (k.toString,false)::l
}
}.reverse
def parse(a:Array[String]):GetOpt = {
def _parse(o:HashMap[Any,Any],l:List[String]):Tuple2[HashMap[Any,Any],List[String]] = l match {
case List() => (o,List())
case h::r => h.toList match {
case '-'::k => {
_params.find { e => e._1 == new String(k.toArray) } match {
case Some(Tuple2(_,true)) => {
if (r.size == 0) throw new InvalidArgumentException
o.update(new String(k.toArray),r.head)
_parse(o,r.tail)
}
case Some(Tuple2(_,false)) => {
o.update(new String(k.toArray),true)
_parse(o,r)
}
case _ => throw new InvalidArgumentException
}
}
case _ => (o,l)
}
}
_parse(new HashMap[Any,Any],a.toList) match {
case Tuple2(o,r) => { _opt = o; _rest = r.toArray }
}
this
}
def getopt(k:String):Any = _opt.isDefinedAt(k) match {
case true => _opt.apply(k)
case _ => false
}
def rest:Array[String] = _rest
}
class CTail(n:Int,f:Boolean,i:File) {
val s:FileInputStream = new FileInputStream(i)
def this(o:GetOpt) =this(o.getopt("n") match { case Some(false) => 10; case n => n.asInstanceOf[String].toInt },o.getopt("f").asInstanceOf[Boolean],new File(o.rest.apply(0)))
def tailn:Unit = {
val BUF_SIZE:Int = 4096
val e:Long = i.length
def _tailn(p:Long,n:Int,b:Array[Byte]):Array[Byte] = {
var t:Array[Byte] = null
var l:Int = n
(p > BUF_SIZE) match {
case true => {
t = new Array[Byte](BUF_SIZE)
s.getChannel.position(p - BUF_SIZE)
s.read(t,0,BUF_SIZE)
}
case _ => {
t = new Array[Byte](p.toInt)
s.read(t,0,p.toInt)
}
}
t = t.reverse.takeWhile { c => if (c == '\n') l = l - 1; (l > 0) }.reverse
((p <= BUF_SIZE) || (l == 0)) match {
case true => t ++ b
case _ => _tailn(p - BUF_SIZE, l, t ++ b)
}
}
print(new String(_tailn(e, n, new Array[Byte](0))))
s.getChannel.position(e)
}
def tailf:Unit = {
def _tailf(b:List[Byte]):List[Byte] = {
val c:Int = s.read
(c >= 0) match {
case true => _tailf(b + c.toByte)
case _ => b
}
}
print(new String(_tailf(List[Byte]()).toArray))
Thread.sleep(100)
tailf
}
def tail:CTail = {
tailn
if (f) tailf
this
}
def close:Unit = s.close
}
object Tail {
def main(args:Array[String]):Unit = {
try {
val o:GetOpt = new GetOpt("n:f").parse(args)
(new CTail(o)).tail.close
} catch {
case e:InvalidArgumentException => println("usage: scala Tail [-n <number of lines>] [-f] file")
case e:FileNotFoundException => print("file not found.")
case e:Exception => e.printStackTrace
}
}
}
|

takeru #6818() Rating-10/12=-0.83
'tail'を実装してください。
巨大なファイルでも効率的に動作するようにしてください。
最低限必要な機能は、
です。
[ reply ]