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

时间:2009-08-17 06:36:48

标签: java console

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

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

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

8 个答案:

答案 0 :(得分:24)

此问题没有可靠跨平台解决方案。实际上,有些情况下无法知道真正的控制台宽度是多少。

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

编辑:只是添加如果用户在启动Java应用程序后在Linux上更改了他/她的xterm的维度,则不会通知Java应用程序,也不会看到新维度反映在LINES和COLUMNS环境变量的副本中!

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

答案 1 :(得分:18)

实际上,Java库已经存在以实现这一点:JLine 2。 (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更新(每Mark - 谢谢,伙计!):

terminalWidth = org.jline.terminal.TerminalBuilder.terminal().getWidth()

答案 2 :(得分:10)

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

另一个答案提到在开始命令之前在脚本中运行tput cols。但是如果你想在Java已经启动之后运行它,使用Runtime.getRuntime().exec(),你会发现tput无法与你的终端通信,因为Java已经重定向了stdout和stderr。作为一种非便携式解决方法,您可以使用神奇的/dev/tty设备,该设备引用当前进程的终端。这可以让你运行这样的东西:

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一起使用。

答案 3 :(得分:4)

Java 6有一个类java.io.Console,但遗憾的是它缺少你要求的功能。使用标准Java库和纯粹的跨平台Java无法获得控制台窗口宽度。

这是一个替代Java console library,它允许您获取屏幕大小,但它包含一个特定于Windows的DLL。您可以获取源代码并将C部分编译到Linux或Mac OS X共享库中,以便它也可以在这些平台上运行。

答案 4 :(得分:3)

我之前一直在研究这个问题。我使用了几种不同的技术。但是,很难拥有真正的跨平台解决方案。

我尝试过尝试这样的事情:

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");

您可以使用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”来获取宽度。然后将该值作为String [] 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吗?

答案 5 :(得分:3)

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

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

"\u001b[s"             // save cursor position
"\u001b[5000;5000H"    // move to col 5000 row 5000
"\u001b[6n"            // request cursor position
"\u001b[u"             // restore cursor position

现在看标准输入法,您应该收到一个看起来像\u001b[25;80R"的连续记录,其中25是行数,80是列。

我首先看到了Lanterna库中使用的代码。

答案 6 :(得分:0)

Python似乎有一个很好的解决方案:11.9.3. Querying the size of the output terminal。我不会屏息等待核心Java中的这个,但您可以使用Jython来使Python功能可用。

答案 7 :(得分:0)

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

这样的命令
ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/c", "mode con");
pb.redirectError(ProcessBuilder.Redirect.INHERIT);

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