如何检查Java程序的输入/输出流是否连接到终端?
我希望Java程序具有不同的默认设置(详细程度,在支持的情况下可能是彩色输出),具体取决于其用途。在 C 中,有一个 isatty() 函数,如果文件描述符连接到终端,它将返回 1,否则返回 0。在Java中是否有等效的?我没有在JavaDoc for InputStream或PrintStream中看到任何东西。
我希望Java程序具有不同的默认设置(详细程度,在支持的情况下可能是彩色输出),具体取决于其用途。在 C 中,有一个 isatty() 函数,如果文件描述符连接到终端,它将返回 1,否则返回 0。在Java中是否有等效的?我没有在JavaDoc for InputStream或PrintStream中看到任何东西。
正如@Bombe已经提到的System.console()适用于检查控制台连接性的简单用例。但是,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) STDIN 是 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-check。我想知道Java的一些目标操作系统是否不支持它。
从技术上讲,使用一些相当简单的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-check。但是,既然你问了这个问题,你可能已经知道了。首先想到的(除了C /C++)是Ruby,Python,Golang和Perl。