有没有办法找到运行我的Java程序的控制台的宽度?
如果可能的话,我希望这是跨平台的......
我不想改变缓冲区或窗口的宽度,我只想知道它的宽度,这样我就可以正确地格式化正在打印到屏幕的文本。
答案 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输出大小,而不是实际大小。只有这种组合才有可能获得实际尺寸。