我可以用Java找到控制台宽度吗?

我可以用Java找到控制台宽度吗?,java,console,Java,Console,有没有办法找到运行Java程序的控制台的宽度 我希望这是跨平台的,如果可能的话 我不想更改缓冲区或窗口的宽度,我只想知道它的宽度,这样我就可以正确格式化正在打印到屏幕上的文本。Java6有一个类Java.io.Console,但不幸的是它缺少您所要求的功能。使用标准Java库和纯跨平台Java无法获得控制台窗口宽度 这里有一个替代方案,允许您获取屏幕大小,但它包括一个Windows特定的DLL。您可能能够获取源代码并将C部分编译到Linux或Mac OS X共享库中,这样它也可以在这些平台上工作

有没有办法找到运行Java程序的控制台的宽度

我希望这是跨平台的,如果可能的话


我不想更改缓冲区或窗口的宽度,我只想知道它的宽度,这样我就可以正确格式化正在打印到屏幕上的文本。

Java6有一个类Java.io.Console,但不幸的是它缺少您所要求的功能。使用标准Java库和纯跨平台Java无法获得控制台窗口宽度


这里有一个替代方案,允许您获取屏幕大小,但它包括一个Windows特定的DLL。您可能能够获取源代码并将C部分编译到Linux或Mac OS X共享库中,这样它也可以在这些平台上工作。

对于这个问题没有可靠的跨平台解决方案。事实上,在某些情况下,不可能知道真正的控制台宽度是多少

例如,在Linux系统上,您通常可以从LINES和COLUMNS环境变量中找到概念上的终端维度。当您调整某些“终端仿真器”窗口的大小时,这些变量会自动更新,但情况并非总是如此。事实上,对于通过telnet协议连接的远程控制台,无法获得用户外壳的实际终端尺寸

编辑:只需补充一点,如果用户在启动Java应用程序后在Linux上更改他/她的xterm的维度,Java应用程序将不会收到通知,并且不会在其
环境变量的副本中看到新维度


编辑2:我的错误:
bash
shell变量,默认情况下它们不会导出到环境中。在运行Java应用程序之前,可以通过运行导出列行来“修复”这个问题。

我以前一直在解决这个问题。我使用了几种不同的技术。然而,很难有一个真正的跨平台解决方案

我试过这样做:

String os = System.getProperty("os.name").toLowerCase();

    //Windows
    if(os.contains("win")){
        System.out.append("Windows Detected");
        //set Windows Dos Terminal width 80, height 25
        Process p = Runtime.getRuntime().exec("mode 80, 25");
    }
    //Mac
    if(os.contains("mac")){
        System.out.println("Macintosh Detected");
        //... I dont know...try Google
    }
    //Linux
    if(os.contains("linux")){
        System.out.println("Linux Detected");
Process p = Runtime.getRuntime().exec(new String[] {
    "bash", "-c", "tput cols 2> /dev/tty" });
// Read the output of this process to get your terminal width
您可以使用String.contains(“export COLUMNS”)方法和user.dir属性读取/测试并将“export COLUMNS”附加到每个Linux用户主目录中的.bashrc文件中

这将允许您在每次java应用程序启动时加载列

然后我会将其传递到临时文件。像这样:

try {
    ProcessBuilder pb = new ProcessBuilder("bash","-c","echo $COLUMNS >/home/$USER/bin/temp.txt" );  
        pb.start();

    }catch (Exception e) {
        System.out.println("exception happened - here's what I know: ");
        e.printStackTrace();
        System.exit(-1);
    }
}
另一个选择是在启动时使用bash脚本执行yor Java.jar。在脚本中,您可以使用“tput cols”获取宽度。然后将该值作为字符串[]arg传递给Java应用程序

像这样:

//#!/bin/bash

//#clear the screen

clear 

//#get the console width and height

c=$[$(tput cols)]

l=$[$(tput lines)]

//#pass the columns, lines and an optional third value as String[] args.

java -jar ~/bin/Plus.jar $c $l $1

为什么这对Java来说是一项如此困难的任务?显然,这是一个编写好API的好地方。我想我们也可以试试Apache.commons.exec?

编辑:请参阅@dave_thompson_085对
ProcessBuilder
的评论,因为这几乎肯定是一种更好的方法

另一个答案提到在启动命令之前在脚本中运行
tput cols
。但是如果您想在Java已经启动之后运行它,使用
Runtime.getRuntime().exec()
,您会发现tput无法与您的终端通信,因为Java已经重定向了stdout和stderr。作为一种完全不可移植的解决方法,您可以使用神奇的
/dev/tty
设备,它指的是当前进程的终端。这样,您就可以运行以下内容:

String os = System.getProperty("os.name").toLowerCase();

    //Windows
    if(os.contains("win")){
        System.out.append("Windows Detected");
        //set Windows Dos Terminal width 80, height 25
        Process p = Runtime.getRuntime().exec("mode 80, 25");
    }
    //Mac
    if(os.contains("mac")){
        System.out.println("Macintosh Detected");
        //... I dont know...try Google
    }
    //Linux
    if(os.contains("linux")){
        System.out.println("Linux Detected");
Process p = Runtime.getRuntime().exec(new String[] {
    "bash", "-c", "tput cols 2> /dev/tty" });
// Read the output of this process to get your terminal width

这对我来说在Linux上是可行的,但我不希望它在任何地方都能奏效。它有望在Mac上工作。它肯定不会在Windows上工作,尽管它可能与Cygwin一起工作。

Python似乎有一个很好的解决方案:。我不会屏住呼吸等待它在核心Java中可用,但您可能可以使用它使Python功能可用。

实际上,Java中已经存在一个Java库来实现这一点:。(SourceForce上有一个旧版本,但到GitHub的链接似乎是最新的。)

在Linux(Mint 14)和Windows(我不知道是什么版本)下,使用JLine 2.11,这对我来说是有效的:

terminalWidth = jline.TerminalFactory.get().getWidth();
JLine承诺也会在Mac上工作

我发现它在Eclipse控制台下返回错误的宽度(比如
1
!)(但即使是Java的本机控制台在Eclipse下也不能工作!),不幸的是,在Cygwin下。但我已经用代码解决了这个问题,这些代码检查不合理的值(
<10
),在这些情况下只使用80

JLine 3的更新(谢谢,伙计!):


对我来说,了解终端窗口(当窗口调整大小时仍然不正确)的唯一方法是使用如下命令

ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/c", "mode con");
pb.redirectError(ProcessBuilder.Redirect.INHERIT);

如果在没有
cmd.exe
部分的情况下运行,则表明找不到该命令。还要注意
重定向错误
部分。如果不使用,则将使用Java输出大小,而不是实际大小。只有通过这种组合,才有可能获得实际的尺寸。

有一个技巧,您可以根据需要使用。它们不提供查询控制台大小的直接方法,但它们确实有一个请求当前光标位置的命令。通过将光标移动到非常高的行和列,然后请求光标位置,可以获得准确的测量值

将其与存储/恢复光标位置的命令相结合,如以下示例所示:

将以下序列发送到终端(stdout)

现在看一下stdin,您应该会收到一个类似于
\u001b[25;80R”
的序列,其中25是行数,80是列数

我第一次在图书馆看到这个

更新:

我知道有四种不同的方法可以实现这一点,但它们都对程序运行的环境或与之对话的终端设备/仿真器做出了某些假设

  • 使用VT100协议。这是w