MG *_*ine 1 terminal posix kotlin-native
我想知道kotlin本机中是否存在一种通过posix调用命令并接收其终端输出的方法。例如,我想使“ git diff”命令正常工作,而不必创建一个临时文件,将输出写入该文件,然后从该文件中读取。
在SO上,我仅找到需要ProcessBuilder的解决方案,由于它是Java库,因此在kotlin-native上不可用。
我找到了想要使用的一段代码,因此将其发布在这里,供将来的观众使用!
fun executeCommand(command: String): String{
val fp: CPointer<FILE>? = popen(command, "r")
val buffer = ByteArray(4096)
val returnString = StringBuilder()
/* Open the command for reading. */
if (fp == NULL) {
printf("Failed to run command\n" )
exit(1)
}
/* Read the output a line at a time - output it. */
var scan = fgets(buffer.refTo(0), buffer.size, fp)
if(scan != null) {
while (scan != NULL) {
returnString.append(scan!!.toKString())
scan = fgets(buffer.refTo(0), buffer.size, fp)
}
}
/* close */
pclose(fp)
return returnString.trim().toString()
}
Run Code Online (Sandbox Code Playgroud)
It's an improved version of exec command for Kotlin Native posted by mg-lolenstine, it throws an exception with command stderr instead of just returning exit(1) (which not always desirable behavior itself), also trim is now optional
import kotlinx.cinterop.*
import platform.posix.*
fun executeCommand(
command: String,
trim: Boolean = true,
redirectStderr: Boolean = true
): String {
val commandToExecute = if (redirectStderr) "$command 2>&1" else command
val fp = popen(commandToExecute, "r") ?: error("Failed to run command: $command")
val stdout = buildString {
val buffer = ByteArray(4096)
while (true) {
val input = fgets(buffer.refTo(0), buffer.size, fp) ?: break
append(input.toKString())
}
}
val status = pclose(fp)
if (status != 0) {
error("Command `$command` failed with status $status${if (redirectStderr) ": $stdout" else ""}")
}
return if (trim) stdout.trim() else stdout
}
Run Code Online (Sandbox Code Playgroud)
通常您可以使用api并POSIX使用一些 I/O 相关函数来达到您的目的forkwait
fun main() {
val childPid: pid_t = fork()
if (childPid == 0) {
val commands = listOf("git", "diff", "HEAD^1", "$projectDir/path/to/file", null)
val cwd = "$projectDir"
chdir(cwd)
memScoped {
execvp(commands[0], allocArrayOf(commands.map { it?.cstr?.ptr }))
}
} else {
wait(null)
}
}
Run Code Online (Sandbox Code Playgroud)
当然,这需要处理很多c风格的代码,所以我还为此写了一个更实用的库
repositories {
mavenCentral()
}
// add dependencies into your native target sourceSet
dependencies {
implementation("com.kgit2:kommand:1.0.1")
}
Run Code Online (Sandbox Code Playgroud)
使用起来也非常简单
fun main(args: Array<String>) {
val diffResult = Command("git")
.args("diff", "HEAD^1", "$projectDir/path/to/file")
.cwd("$projectDir")
.spawn()
.output()
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
69 次 |
| 最近记录: |