在java控制台中打印一行(与'\ n'相反)

问题描述 投票:19回答:1

Foreword

我在其他语言中看到了一些与此相关的问题,并对此进行了相当多的研究。首先,在我们开始走下兔洞之前,我必须说明我为什么这样做。我正在打印一个二叉树,我找到了一种方法来做到这一点,我认为没有其他人找到它(在网上的任何地方找不到它我永远搜索过)。它解决了许多与间距和冲突相关的问题,我可能会在以后提供它作为Prettyprint Btree问题的答案。无论如何,执行上述操作的一个重要部分是能够将换行(光标)向上移动一行。我也会安排将一个回车移动一行。

我已经对这个名为“编辑1-3”的问题进行了三次编辑。

我的特定Windows版本(可能相关):Windows 10 v1607操作系统版本:14393.2035

The problem??

问题是使用ANSI转义字符很容易做到这一点

ANSI转义码:https://en.wikipedia.org/wiki/ANSI_escape_code

使用“\ 033 [A”是我想要实现的特定代码(从有关在python中移动一行的问题得到它)。

The problem

所以问题解决了吗?哦不,甚至不接近。问题是,显然Windows有这个“”精彩“”更新可能已经打破了ANSI /控制台相关的一切。下面链接到有关此问题,但具有不同的ANSI要求,但根本问题是相同的。

How to print color in console using System.out.println?

tl:dr由于某些原因它不适用于Windows,你需要一个大型库来执行此操作或其他操作。

Sooo然后我尝试对更新本身做一些深入的研究,为什么这恰好是特定于Windows的(当然),我被引导到了这一点。

Windows问题的根本原因:https://github.com/Microsoft/WSL/issues/1173

tl; dr:基本上,更新更改了cmd.exe的默认设置,cmd.exe是java使用的默认控制台。更改的是如何为“子应用程序”AKA java处理ANSI代码的控制台设置(使用控制台但不是控制台本身的东西)。默认值在更新之前,子应用程序继承了启用ANSI的默认控制台。现在(因为显然,以前的默认设置破坏了东西)他们改变了它,以便子应用程序不从控制台继承默认设置。这意味着如果java想要启用ANSI,java必须自己有效地设置此控制台模式。显然有很多库用于java命令,但是有很多可用的库,存在一些问题。首先,他们需要maven,我不想要maven,我也不喜欢需要一百万个额外的库来做一些非常简单的事情,它增加了我的代码所依赖的事物的数量(这很糟糕)。所以我试图避免简单的解决方案,如“只使用JANSI”到setConsoleMode for ANSI。

What I've tried after this

在我完成阅读/理解后,我尝试进入我的注册表编辑器并尝试更改控制台的默认设置(cmd.exe),以便始终为子应用程序启用ANSI(AKA java)。有人在GitHub的讨论中提出过建议,但令我惊讶的是,具体设置对我来说并不存在。 (它应该在计算机 - > HKEY_CUURENT_USER - >“TrimLeadingZeros”和“WindowAlpha”之间的控制台中)。

Try 2

由于我无法编辑控制台设置而没有大型库充满了我不想要的东西,我尝试在盒子外面思考并且在java设置中搞砸了。我发现java确切地设置了它的控制台,并发现我可以更改该设置以在java中使用不同的控制台。我最近安装了git,并且知道git bash可用,所以我尝试使用下面的问题(以及谷歌一般)作为起点。

https://superuser.com/questions/1196463/start-sh-exe-bash-with-given-path

Third time is the charm?

我无法找到合适的工作。它没有返回任何错误或做任何新的事情,就像所有。它甚至被设置为'当前项目',所以当我运行我的项目时,它应该做些不同的事情吗?我相信问题的一部分是我的根git文件夹很棘手(不在程序文件中)。这可能是因为我使用的计算机是一台工作计算机,可能有一些设置会影响安装git的位置,我不知道但我知道的是当我更改控制台时我尝试了这条路径:

C:\ Users \用户abbotts1 \应用程序数据\本地\程序\的Git \ BIN \ bash.exe

我也尝试过:

C:\ Users \用户abbotts1 \应用程序数据\本地\程序\的Git \ bash.exe

C:\ Users \用户abbotts1 \应用程序数据\本地\程序\的Git \ BIN \ sh.exe

“C:\ Users \ abbotts1 \ AppData \ Local \ Programs \ Git \ bin \ sh.exe”--login -i

每次更改控制台后我都试过这段代码:

public class ExpressionEvaluator {

    public static void main(String[] args) {
        System.out.println("1");
        System.out.println("\033[A");
        System.out.println("2");
    }
}

我总是得到:

1

额外的线在这里

2

作为输出。如果我删除了“向上移动光标”ANSI println语句,我得到了:

1

2

我想要的是:

2

1

(总的来说,我可以自由地向上移动一条线)

我也尝试过制作它们的印刷语句,但也没有用。

So I'm now at wits end

所以这就是我想要的,答案如下:

  1. 一种非侵入性的方法来更改cmd.exe的设置,以允许像java这样的子应用程序在运行时使用ANSI BY DEFAULT
  2. 或者一个非侵入式库,它不需要maven和其他一百万个其他东西来启用ANSI所以我可以在控制台中运行java并获得我想要的输出
  3. 或者是一种程序化的解决方法,它允许我在没有这整个ANSI的情况下有效地打印一行
  4. 或者帮助配置IntelliJ控制台,以便我可以实际使用不同的控制台并使用ANSI打印一行

To address the obvious concerns

由于1和4是超级用户问题,2是'我需要一个库'和offtopic我在这里更多地谈论第3点。如果没有解决方法,答案是其中一个offtopic,只是告诉我没有解决方法。我不知道如何提出这个问题,因为它是一个“编程特定问题”,它只有许多解决方案,其中一些不是“关于主题”,因为它们不是编程解决方案。如果唯一的答案是'解决方案不在这里',那么我会在适当的地方提问。当我去其他地方问我是否应该删除这个问题时,请告诉我。

What I think might work for on topic part of this

由于3是关于主题的,我将讨论我在想什么:

也许我可以制作某种系统只打印到某些数组而不是上下移动线(即有一个数组来表示线,遍历树而不是上下移动线,只需将数组切换到打印到)。我不认为这是非常有效的,它浪费阵列和处理能力,但如果它是一个解决方案,我愿意听到它。这就是我能想到的全部,但我尝试过的大多数尝试都是为了让ANSI工作。

For future reference:

通过多个非主题解决方案/解决方案问题提出这些问题的适当方式是什么?最好不要问他们吗?涉及问题的解决方案是否构成变色龙问题?我不想把元效应带给自己。

Edit 1: where I'm at so far:

我再次尝试了整个git bash的事情,男孩是一个过程。终端中的实际git bash路径需要引用后面带有--login -I参数的引号。例如:

C:\ Git \ bin \ sh.exe --login -i

此设置适用于java终端。那么你必须将一个名为PATH的Windows环境变量设置为java JDK。转到您的路径环境变量(有一百万个和一个youtube视频),并为您的JDK设置一个名为PATH的新变量。例如:

C:\ Program Files \ Java \ jdk-10.0.1 \ bin

这个问题:

How can i make gitbash find the javac command?

广泛地完成这个过程

Tl; dr你必须设置一个windows路径变量,以便git bash识别javac和java命令。

完成后,您需要像在任何终端中一样运行java和javac命令。顺便说一句,因为git bash中的路径需要两个'\'符号而不是普通的'\',所以你的源目录路径可能如下所示:

C:\ IdeaProjects \计算器的\ src \

然后你运行:

javac ClassName.java

java ClassName

然后,它实际上不打印ANSI输出,它打印原始转义字符。另外,我发现我使用的是错误的转义序列(我的错误号码代表'esc'按钮,因为'esc'键表示为某个数字,但是我使用了错误的十六进制数字,如x330或东西)。我还了解到符号是这样的:

'esc key hex number'+'['+'参数十六进制值以逗号分隔'

所以这可能看起来像:

\ x1B [A

其中实际的字母和数字是十六进制值的东西(没有明显的0x ...)和第一个转义十六进制值有一个x(为什么?)。无论如何,当用Java作为字符串运行它们时,你需要使用额外的'\'来转义转义字符(对吧?),例如,代码可能如下所示:

System.out.println("\\\x1B [A");

我只是注意到堆栈溢出也逃脱了这些,所以我实际上有三个'\'但是对于你们来说,它只显示两个'\',奇怪吧?无论如何回到我所说的

但仍然,输出实际上不起作用!这就是我所在的地方。我已经完成了上述操作,我99.9%知道git bash安装正确并且运行正常但是当我运行时:

public class ExpressionEvaluator {
    public static void main(String[] args) {
        System.out.println("1");
        System.out.println("\\x1B [A");
        System.out.println("2");
    }
}

我在java控制台中得到这个(不是git bash ??):

1

\ x1B [A

2

这在git bash中:

1

\ x1B [A

2

我真正想要的是:

2

1

因为ANSI转义字符应该移动我的光标/换行/其他,向上一行。如果我运行上面的代码但是使用ANSI代码,则会发生同样的事情:“\ x1B [F”。仅输出原始ANSI。我很确定git bash应该是'原生于ANSI的意识',我看到人们在网站上说这些,所以我不知道为什么它不起作用。

我仍然不确定这些是两个单独的控制台输出还是相同的控制台输出。我真的不能这么说,如果有人想发表评论说'是的,它是同一个假人',我会很感激,因为我无法在网上找到一个明确的消息来源。我认为只有IntelliJ中的控制台设置才能表明这一点。

我听说有关TERM变量的传闻需要在Windows上设置或以其他方式操作。我已经检查了自己使用的是什么:

echo $ TERM

在git bash中我回来了:

cygwin的

所以我不确切地知道这是好还是坏因为我已经完成了你能想到的所有搜索术语,并且它们都导致了'git bash colors not working'的结果的相同基本页面,其中大部分都是涉及安装maven / jansi(不想或不需要它)的Windows 7(没有它)或其他非Java语言并使用其他非IntelliJ的IDE。一些有我特定要求的页面已经说过关于TERM应该是xterm或者其他一些东西,比如xterm-256或者'color'输出的东西,就像这样。我对这些东西很不熟悉,所以我甚至都不知道从哪里开始。

Too long give us a tl;dr

我需要知道为什么git bash打印原始ANSI而不是实际使用ANSI。

我知道的

我正在使用带有IntelliJ的git bash,99.9%确定我的路径设置正确,我可以从git bash运行我的java类,我将它设置为IntelliJ终端,我目前将windows TERM变量设置为cygwin 。

我不知道的

我不知道TERM需要什么,也无法在网上找到它,我不知道当我点击绿色箭头'run'时出现的IntelliJ控制台是否与git bash控制台相同,并且我无法弄清楚是否有其他事情阻止我实际解释ANSI。

我需要的

我需要一个简单的解释,直接来自r / ELI5,git bash有什么问题,如果有什么以及如何修复它。如果它不能简单解释或没有任何错误,那么也许我会尝试另一个所谓的“原生ANSI识别”终端。我认为Powershell是列出的另一种选择。我最好的选择是TERM变量需要是其他东西,或者git bash从来没有真正本身具有ANSI意识和能力,首先。我已经看到其他问题与颜色相同的问题,但他们的修复是针对旧版本/不同的语言和东西,或者他们实际上没有工作。我还没有找到一个很好的页面'git bash输出IntelliJ中的原始ANSI',我现在已经使用了几个小时的变量。我所能得到的只是GitHub长期讨论与此相关的“错误”,他们让我困惑,不会导致解决方案,可能是活跃的或者只是不包含任何解决方案。

Edit 2

在做了一些研究后,我了解到我以前的转义码是正确的:

\ 033 [A

\ X1B [A

应该是类似的。

我还了解到,我所使用的控制台不是问题,而是Windows本身。我现在知道这个,因为我已经尝试在cmd.exe,git bash和powershell上编译和运行。要更改之前谈到的默认设置(控制台不支持子应用程序的ansi),您必须通过程序本身显式启用它,而不是依赖于控制台或其他东西。

链接到这里用Python解释这个问题:

How to use the new support for ANSI escape sequences in the Windows 10 console?

tl;博士

他们使用的方法叫做getConsoleModesetConsoleMode以及VIRTUALTERMINALPROCESSING标志。显然你需要使用它们来实际设置控制台模式以支持ANSI。我目前不知道那些是隐藏在某处的java中的东西,还是(可能)需要添加到基本java库中的东西。我将尝试弄清楚他们是如何从这个问题中获得ctypes的东西(似乎是他们导入来起诉这些方法)并获得我需要的方法。一旦我这样做,我会把它作为答案发布,除非你们中的一个人在我做之前弄明白并且可以更好地解释它。

显然,如果你只是从控制台使用它们,那么转义序列工作正常但是如果你使用“子应用程序”那么它们就不起作用了。所以至少我们现在肯定知道问题的根本原因。

Edit 3

发现这与控制台虚拟终端序列部分(左手导航栏)高度相关:

https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences

这在底部附近有一个完整的C实现,如何使控制台能够读取ANSI。显然,这根本不需要库,但实际更改控制台默认使用这样的代码的过程需要sysadmin权限,对程序文件的深入了解以及许多其他事情(至少如果你在之前当颜色支持被更改时,Windows 10会更新)。现在它仍默认处于禁用状态,但可以启用。我还不知道如何直接从控制台尝试ANSI。我试过多次

echo \ x1B [(此处插入ANSI代码)

但是没有一个命令似乎可以在任何终端(cmd,git bash,powershell)中工作。他们只返回原始代码

\ x1B [(无论ANSI代码是什么)

我显然对控制台很陌生,所以我可能会使用错误的命令,如果可以随意启发我,但我见过的例子使用echo。无论如何,我认为直接从终端调用ANSI应该可以工作,因为它默认只启用它而不是子应用程序(发布Windows 10更新)但也许它不是,默认情况下它可能被禁用,甚至在启用时仍然禁用它应用程序(Java),除非在所述子应用程序(java)中显式更改。我将尝试查看是否可以直接从控制台启用ANSI,或者链接的C代码是否需要直接移植到Java或在控制台中运行才能工作。问题是我不知道如何获得C代码使用的import / includes并将其用于java中的代码。我宁愿不仅仅接受C中的编码“解决方案”并尝试将其与java代码一起使用,我宁愿翻译,更好地理解它并拥有自己的代码来做同样的事情。

我被告知的另一个选项叫做ANSICON,就像某种插件一样,你在控制台中使用-i标志安装,并且应该至少在控制台中启用ANSI。我找到了这个

https://community.liferay.com/blogs/-/blogs/enable-ansi-colors-in-windows-command-prompt

以上解释了这个过程的细节。

我的具体Windows版本和更新版本

我学到的另一件事是Windows 10的特定版本更改了ANSI控制台行为的'更新'就像windows 10 v1151之类的东西,我会尝试找到直接来源的网页,但我目前有windows 10 v1607所以我想我应该好。其中包括实际的操作系统构建,我有14393.2035,我认为在我之前的一个链接中被认为是对这个过程的一个特别中间的更新(我相信它是关于更新的整个GitHub讨论的那个,你可以找到它在这里:https://github.com/Microsoft/WSL/issues/1173)。我有一台工作计算机,所以我不能真正进行系统更新,因为我不是管理员而且我怀疑IT会让实习生更新工作计算机。

无论如何,我会继续尝试看看我是否可以将C代码转换为java,我将测试它然后尝试发布答案。如果你领先于我,请告诉我。

java io ansi windows-console
1个回答
1
投票

您在“编辑2”(https://stackoverflow.com/a/36760881/309816)中引用的python方式只是调用特定于Windows的本机代码(kernel32,它是非可移植的)来“修复”它。

我想你可以这样做,并希望在Java中做同样的事情(即在检测Windows时调用kernel32)...

用于在Java中实现相同功能的非常轻量级的库是JNA,它具有针对kernel32的开箱即用包装器(请参阅:https://java-native-access.github.io/jna/4.2.1/com/sun/jna/platform/win32/Kernel32.html

你似乎在追求这种方法:https://java-native-access.github.io/jna/4.2.1/com/sun/jna/platform/win32/Wincon.html#SetConsoleMode-com.sun.jna.platform.win32.WinNT.HANDLE-int-

希望这对你有用。

编辑:从技术上讲,你只需要jna.jar(参见这里开始:https://github.com/java-native-access/jna/blob/master/www/GettingStarted.md),但我建议你也使用jna-platform.jar,这样你就不需要在运行时编写为kernel32生成映射的代码了。

JNA的主页:https://github.com/java-native-access/jna

我认为添加1(或者如果你添加jna平台的话2)具有非常特定范围的jar(在没有所有JNI准备开销的情况下进行本机调用)是足够轻量级的。您不需要生成任何标头,也不需要在编译过程中更改任何内容。只需将这些jar添加到类路径中即可。

你还应该在你的问题中澄清这是关于Windows的。也许可以将标题编辑为:“在Windows上用java控制台打印一行(与'\ n'相反)”,因为这实际上是关于要用Java解决的特定于平台的问题。

© www.soinside.com 2019 - 2024. All rights reserved.