Scala和Kotlin脚本编程
Scala和Kotlin作为运行在JVM上的编程语言,解决了Java的很多痛点。今天我们来聊聊如何将Scala和Kotlin作为脚本语言使用(Java不支持以脚本形式运行哦)。
Kotlin脚本编程
Kotlin脚本的扩展名为kts
,运行命令为kotlinc -script <脚本文件名.kts>
HelloWorld示例
下面我们来看一个HelloWorld示例:
新建名称为Main.kts
的Kotlin脚本文件,内容如下:
println("你好 ${if (args.isNotEmpty()) args[0] else ""}!")
可以看到脚本程序不需要主函数,Kotlin脚本以args
参数接收用户输入(args是一个Array<String>
类型的数组)
在命令行执行:kotlinc -script Main.kts 高寒
得到脚本运行结果为:你好 高寒!
调用外部命令
如果我们想在Kotlin脚本中调用外部的命令或者程序需要怎么做呢?
使用Java API中提供的Runtime.getRuntime().exec()
函数或者ProcessBuilder
类创建一个Process
对象调用外部命令。
下面以调用系统ls
命令作为示例程序进行演示说明。
import java.lang.Runtime
val process: Process = Runtime.getRuntime().exec("ls /Users/TheOneGIS/Desktop")
process.waitFor()
process.inputStream.reader().use {
println(it.readText())
}
或者
import java.lang.ProcessBuilder
val process: Process = ProcessBuilder("ls", "/Users/TheOneGIS/Desktop").start()
process.waitFor()
process.inputStream.reader().use {
println(it.readText())
}
在命令行中执行kotlinc -script Main.kts
,输出结果如下:
11
data
raw
[这里有一个空行]
注意:
Runtime.getRuntime().exec()
函数中直接输入命令名称加参数组成的字符串ProcessBuilder
使用多个参数进行命令名称和参数进行类的初始化- 命令中的路径名称不能使用
~
特殊字符,否则会出错。建议使用全路径。 Process.waitFor()
等待调用的外部程序执行完毕再接着执行脚本后续代码。- 从输出结果的InputStream中得到文本输出,可以看到最终的文本输出每一行之后都会增加一个换行符。
Scala脚本编程
Scala脚本的扩展名仍为scala
,运行命令为scala <脚本文件名.scala>
,和普通的Scala类一样。
HelloWorld示例
新建名称为Main.scala
的Scala脚本文件,内容如下:
println(s"你好 ${if (args.nonEmpty) args(0) else ""}!")
可以看到和Kotlin脚本程序一样不需要主函数,Scala脚本同样以args
参数接收用户输入(args是一个Array[String]
类型的数组)
在命令行执行:scala Main.scala 高寒
得到脚本运行结果为:你好 高寒!
调用外部命令
在Scala中可以调用Java方法,我们可以直接使用上面类似Kotlin的方式,但是Scala中为我们提供了更加便捷的方法来调用外部命令或程序,下面我们来看一下吧!
- 使用
Process
的!
方法,得到执行结果的状态码,一般0表示成功 - 使用
Process
的!!
方法,得到执行结果的文本输出 - 使用
Process
的lazyLines
方法,将得到保存在LazyList[String]
结构的输出中(延迟执行)
注意:这里的Process
类是Scala类库中提供的,前面在Kotlin中使用的Process
类是Java类库中提供的。
我们先来看第一种方式:
import sys.process._
Process("ls /Users/TheOneGIS/Desktop").!
在命令行中运行scala Main.scala
,得到执行结果:
11
data
raw
Process
的!
方法是有返回值的,这里我们直接舍弃了,并不关心ls
的返回值,我们只关心ls
命令的输出结果。
再看第二种方式:
import sys.process._
val results = Process("ls /Users/TheOneGIS/Desktop").!!
println(results)
在命令行中运行scala Main.scala
,得到执行结果:
11
data
raw
[这里有一个空行]
可以看到results
字符串是给ls
命令的每个输出字符后面都加了换行符。
再看第三种方式:
import sys.process._
val results = Process("ls /Users/TheOneGIS/Desktop").lazyLines
results.foreach(println)
输出结果和第一种方式一样,不过当需要获取最后输出并且需要对输出进行操作的时候我最喜欢使用第三种方式,不需要对输出进行进一步处理的时候我喜欢使用第一种方式。
Scala和Kotlin脚本编程的异同
- Scala脚本的扩展名和执行方式和普通Scala类一样;Kotlin脚本的扩展名为
kts
,执行的时候需要加-script
参数 - Scala提供了对于外部命令调用的快捷方法;Kotlin主要依靠Java类库进行外部命令调用
- 在IntelliJ IDEA中可以直接运行Kotlin脚本,但是不支持直接运行Scala脚本
- IntelliJ IDEA提供了对Ammonite项目的支持,可以运行Ammonite Scala脚本
注:Ammonite项目扩展了Scala的脚本功能,添加了很多额外的特性,甚至提供了一个基于Scala的Shell(类似于Bash Shell)。用Ammonite写的Scala脚本扩展名为sc
,使用amm
命令进行执行。感兴趣的童鞋可以去围观该项目。