How can I check if a Java program’s input/output streams are connected to a terminal?

System.console() vs isatty()

System.console(), as already mentioned by @Bombe, works for simple use cases of checking console-connectedness. The problem with System.console() however, is that it doesn’t let you determine whether it’s STDIN or STDOUT (or both or neither) that is connected to a console.

The difference between Java’s System.console() and C’s isatty() can be illustrated in the following case-breakdown (where we pipe data to/from a hypothetical Foo.class):

1) STDIN and STDOUT are tty

%> java Foo
System.console() => <Console instance>
isatty(STDIN_FILENO) => 1
isatty(STDOUT_FILENO) => 1

2) STDOUT is tty

%> echo foo | java Foo
System.console() => null
isatty(STDIN_FILENO) => 0
isatty(STDOUT_FILENO) => 1

3) STDIN is tty

%> java Foo | cat
System.console() => null
isatty(STDIN_FILENO) => 1
isatty(STDOUT_FILENO) => 0

4) Neither STDIN nor STDOUT are tty

%> echo foo | java Foo | cat
System.console() => null
isatty(STDIN_FILENO) => 0
isatty(STDOUT_FILENO) => 0

I can’t tell you why Java doesn’t support better tty-checking. I wonder if some of Java’s target OS’s don’t support it.

Using JNI to call isatty()

It technically is possible to do this in Java (as stephen-c@ pointed out) with some fairly simple JNI, but it will make your application dependent on C-code that may not be portable to other systems. I can understand that some people may not want to go there.

A quick example of what the JNI would look like (glossing over a lot of details):

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 (assumes matching ttyutils.h), compiled to 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;
}

Other languages:

If you have the option of using another language, most other languages I can think of support tty-checking. But, since you asked the question, you probably already know that. The first that come to mind for me (aside from C/C++) are Ruby, Python, Golang and Perl.

Leave a Comment