System.console() 与 isatty()
System.console(),正如@Bombe 已经提到的,适用于检查控制台连接的简单用例。然而,System.console() 的问题在于它无法让您确定连接到控制台的是 STDIN 还是 STDOUT(或两者都或两者都不是)。
Java 的 System.console() 和 C 的 isatty() 之间的区别可以在以下案例分解中说明(我们通过管道将数据传入/传出假设的 Foo.class):
1) STDIN 和 STDOUT 是 tty
%> java Foo
System.console() => <Console instance>
isatty(STDIN_FILENO) => 1
isatty(STDOUT_FILENO) => 1
2) STDOUT 是 tty
%> echo foo | java Foo
System.console() => null
isatty(STDIN_FILENO) => 0
isatty(STDOUT_FILENO) => 1
3) 标准输入是 tty
%> java Foo | cat
System.console() => null
isatty(STDIN_FILENO) => 1
isatty(STDOUT_FILENO) => 0
4) STDIN 和 STDOUT 都不是 tty
%> echo foo | java Foo | cat
System.console() => null
isatty(STDIN_FILENO) => 0
isatty(STDOUT_FILENO) => 0
我无法告诉你为什么 Java 不支持更好的 tty 检查。我想知道Java的某些目标操作系统是否不支持它。
使用JNI调用isatty()
技术上是可以用一些fairly simple JNI 在 Java 中做到这一点(正如 stephen-c@ 指出的那样),但它会使您的应用程序依赖于可能不可移植的 C 代码到其他系统。我可以理解有些人可能不想去那里。
JNI 外观的简单示例(忽略了很多细节):
Java:tty/TtyUtils.java
public class TtyUtils {
static {
System.loadLibrary("ttyutils");
}
// FileDescriptor 0 for STDIN, 1 for STDOUT
public native static boolean isTty(int fileDescriptor);
}
C:ttyutils.c(假设匹配ttyutils.h),编译成libttyutils.so
#include <jni.h>
#include <unistd.h>
JNIEXPORT jboolean JNICALL Java_tty_TtyUtils_isTty
(JNIEnv *env, jclass cls, jint fileDescriptor) {
return isatty(fileDescriptor)? JNI_TRUE: JNI_FALSE;
}
其他语言:
如果您可以选择使用其他语言,我能想到的大多数其他语言都支持 tty-checking。但是,既然你问了这个问题,你可能已经知道了。我首先想到的(除了 C/C++)是Ruby、Python、Golang 和 Perl。