- 追加された行はこの色です。
- 削除された行はこの色です。
*Processのラッパー [#q24a5bdb]
Java言語での不都合、といっても書き方がじょちょうになる程度
を改善するためにラッパーを書きます。
#contents
*特徴などの紹介 [#t848d4e7]
DOSのコマンドでディレクトリの情報を表示するコマンドといえば、
-DIR
ですが、私のつくったPrototypeをインポートすれば、
"DIR".exe
と書くだけでコマンドラインで実行するようなことがきるようになりますし、さらに工夫したメソッドも用意してあります。
**ProcessScala [#jf3e6498]
**メリット [#e0a2df5e]
-jarファイルで圧縮していないので、自分でメソッドを増やしていくことが簡単
-Javaの標準のRuntimeメソッドではInputStreamを自動的に閉じないが、このメソッドは閉じるなど堅牢な作りにしてある。
-通常dirコマンドは "cmd /c dir"と記述しければならないが、その文字を補完するようにしている
-プロセス処理に必要なクラスのimport等を完全にカプセル化したので簡単になった。
**JavaScriptのPrototype.jsにインスパイアされて、名前をつけました。 [#e52f7ec6]
*使用例 [#u98179b9]
**ProcessMain.scala [#y0cebec9]
package test
object ProcessMain {
def main(args: Array[String]): Unit = {
//Prototype.scalaを用意した後、次の一行で呼び出す。
import Prototype._
println("--例1 直接こんな感じでシェルを呼び出せます。--")
"dir ".exe //ディレクトリの情報が表示される
println("--例2 値を文字列変数で取得可能です。--")
println("dir /w".exeresult)
println("--使い方3--")
"dir /w".exe_eachLine{line =>
println(line)
}
"使い方4".p
"文字列の表示はprintlnと同じ意味のpを用意しました。違いは値を返します。".p
"2回表示して実行する例".p
"echo aaaa".p.p.exe
"実行ごとにプロセスが生成されるので、ディレクトリの移動は意味がありません".p
"echo zzzz".exe
"cd c:\\".exe
"dir".exe
println(currentdir)
}
}
**Prototype.scala [#v5fd454b]
package test
import java.io._
import scala.util.DynamicVariable
import java.lang.Process
import java.io._
case class ProcessScala(charset :String) {
//--------------------------------
// Object記述部分
//--------------------------------
object Prototype {
var currentdir = ""
if (currentdir == ""){
}
implicit def wrapBufferedReader(src: BufferedReader) = {
new WrapBufferedReader(src)
}
implicit def wrapString(src: String) = {
new WrapText(src)
}
}
//--------------------------------
// class記述部分
//--------------------------------
//BufferedReaderにeachLineメソッドを拡張する
class WrapBufferedReader(src: BufferedReader) {
def eachLine(f: String => Unit) {
var line:String = null
while({line = src.readLine ; line != null}){
f(line)
}
}
}
//Stringを拡張するメソッド
class WrapText(string : => String){
def gsub(pat : String,afterstring :String) :String = {
string.replaceAll(pat,afterstring)
}
//プロセスを実行し結果の文字列を返す。
def exeresult() :String = {
var p:ProcessScala = new ProcessScala
p.exeresult(string)
}
//実行して結果を出力する
def exe() = {
println(exeresult)
}
implicit def wrapArray_String(array: Array[String]) = {
new WrapArray_String(array)
}
//実行して結果を出力する
def exe_eachLine(f: String => Unit) {
val lines = exeresult.split("\n")
lines.each{line=>
f(line)
}
}
//表示println
def p() :String = {
println(string)
string
}
}
//Array[String]を拡張するクラス
class WrapArray_String(array : Array[String]){
def each(f: String => Unit){
for (item <- array){
f(item)
}
}
}
class ProcessScala(charset :String) {
val dynamicvariable= new DynamicVariable[Process](null)
var stdout :BufferedReader = null;
var stderr :BufferedReader = null;
var stderr :BufferedReader = null;
//var stdin :BufferedWriter = null;
//デフォルトのキャラクタコードを使う
def this() = this("")
//自動的にDestroyするProcess
def exec(cmd:String)(block : => Unit){
var process :Process = null
try {
process = Runtime.getRuntime.exec(cmd)
stdout = getBufferdReader(process.getInputStream(),"")
stderr = getBufferdReader(process.getErrorStream(),"")
dynamicvariable.withValue(process){block}
} catch {
//dir とか 普通に実行させたい
case e:java.io.IOException =>{
try {
if (cmd.length < 7 || !(cmd.substring(0,6) == "cmd /c")){
//cmd /cを追加してみる
process = Runtime.getRuntime.exec("cmd /c " + cmd)
stdout = getBufferdReader(process.getInputStream(),"")
stderr = getBufferdReader(process.getErrorStream(),"")
dynamicvariable.withValue(process){block}
dynamicvariable.withValue(process){block}
//process.waitFor
}
} catch {
case e =>println (cmd + " is exsits?")
throw e
}
}
} finally {
//子プロセス呼び出し後は,必ず,ストリームを閉じる
if (process != null) {
process.getErrorStream().close();
process.getInputStream().close();
process.getOutputStream().close();
process.destroy();
}
if (stdout != null) {
try {stdout.close} catch {case e:IOException => }
}
if (stderr != null) {
try {stderr.close} catch {case e:IOException => }
}
}
}
//実行結果の戻り値を返します。
def exeresult(command :String) = {
var result = ""
exec(command){
var line:String = null
while({line = stdout.readLine ; line != null}){
result = result + line + "\n"
}
}
result
}
//get dynamic variable's value
def $_()={
dynamicvariable.value
}
def getBufferdReader(is:InputStream, charset :String):BufferedReader = {
if (charset == "") {
new BufferedReader(new InputStreamReader(is));
} else {
try {
new BufferedReader(new InputStreamReader(is, charset));
} catch {
case e: UnsupportedEncodingException => {
throw new RuntimeException(e);
}
}
}
}
}
**processMain.scala [#x75be347]
呼び出し例をあげておきます。
*今後の方針 [#l7bfc640]
-問題99での回答で作成したメソッドを標準的に呼び出せるようにしておきたい。
-利用者側に極力負担がかからないようにしたい
package test
object ProcessMain {
def main(args: Array[String]): Unit = {
var p:ProcessScala = new ProcessScala
p.exec("dir"){
var line:String = null
while({line = p.stdout.readLine ; line != null}){
println(line)
}
}
}
}