Come posso verificare se i flussi di input / output di un programma Java sono collegati a un terminale?

StackOverflow https://stackoverflow.com/questions/1403772

  •  05-07-2019
  •  | 
  •  

Domanda

Vorrei che un programma Java avesse diverse impostazioni predefinite (verbosità, possibilmente output colorato dove supportato) a seconda del suo utilizzo. In C, esiste una funzione isatty () che restituirà 1 se un descrittore di file è collegato a un terminale e 0 in caso contrario. Esiste un equivalente per questo in Java? Non ho visto nulla in JavaDoc per InputStream o PrintStream.

È stato utile?

Soluzione

System.console () restituirà la console alla quale l'applicazione è connessa se è connessa, altrimenti restituisce null . (Nota che è disponibile solo da JDK 6 in poi.)

Altri suggerimenti

System.console () vs isatty ()

System.console (), come già accennato da @Bombe, funziona per casi d'uso semplici di verifica della connessione alla console. Il problema con System.console (), tuttavia, è che non consente di determinare se è STDIN o STDOUT (o entrambi o nessuno dei due) ad essere collegato a una console.

La differenza tra Java System.console () e le isatty () di C essere illustrato nella seguente suddivisione dei casi (in cui vengono convogliati i dati da / verso un'ipotetica classe Foo):

1) STDIN e STDOUT sono 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) Né STDIN né STDOUT sono tty

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

Non posso dirti perché Java non supporta un migliore controllo tty. Mi chiedo se alcuni dei sistemi operativi di destinazione Java non lo supportano.

Uso di JNI per chiamare isatty ()

Tecnicamente è possibile farlo in Java (come sottolineato da stephen-c @) con alcuni JNI abbastanza semplice , ma renderà la tua applicazione dipendente dal codice C che potrebbe non essere portabile con altri sistemi. Posso capire che alcune persone potrebbero non voler andarci.

Un rapido esempio di come sarebbe il JNI (passando in rassegna molti dettagli):

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 (presuppone che corrisponda a ttyutils.h ), compilato in 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;
}

Altre lingue:

Se hai la possibilità di usare un'altra lingua, la maggior parte delle altre lingue mi viene in mente di supportare il controllo tty. Ma, dal momento che hai posto la domanda, probabilmente lo sai già. I primi che mi vengono in mente (a parte C / C ++) sono Ruby , Python , Golang e Perl .

La risposta breve è che non esiste un equivalente diretto di 'isatty' in Java standard. C'è stato un RFE per qualcosa di simile nel database dei bug Java dal 1997, ma solo ha avuto 1 un voto misero.

In teoria, potresti essere in grado di implementare 'isatty' usando la magia JNI. Ma ciò introduce ogni sorta di potenziali problemi. Non avrei nemmeno pensato di farlo da solo ...


1 - Le votazioni per i bug Java da correggere sono scomparse nel periodo in cui Oracle ha rilevato Sun.

Puoi usare la jnr-posix per chiamare metodi posix nativi da Java:

import jnr.posix.POSIX;
import jnr.posix.POSIXFactory;
import java.io.FileDescriptor;

POSIX posix = POSIXFactory.getPOSIX();

posix.isatty(FileDescriptor.out);

Se non vuoi compilare tu stesso la sorgente C, puoi usare la libreria Jansi. È molto più piccolo di jnr-posix

<dependency>
  <groupId>org.fusesource.jansi</groupId>
  <artifactId>jansi</artifactId>
  <version>1.17.1</version>
</dependency>

...

import static org.fusesource.jansi.internal.CLibrary.isatty;

...

System.out.println( isatty(STDIN_FILENO) );
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top