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

Red*_*ted 19 java io ansi windows-console

前言

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

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

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

问题??

问题是使用ANSI转义字符很容易完成

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

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

问题

所以问题解决了吗?哦不,甚至不接近.该问题是,显然窗户上挂着这个""" 精彩 '’"更新,可能有破产一切ANSI /控制台有关.下面链接到有关此问题,但具有不同的ANSI要求,但根本问题是相同的.

如何使用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必须自己有效地设置此控制台模式.显然有大量的libary用于java命令,但是有很多可用的库存有一些问题.首先他们需要maven,我不想要maven,我也不喜欢 喜欢需要一百万个额外的库来做一些非常简单的事情,它增加了我的代码依赖的东西(这很糟糕).所以我试图避免像"只使用JANSI"这样的简单解决方案setConsoleMode 对于ANSI.

我在此之后尝试过的

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

试试2

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

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

第三次是魅力?

我无法找到合适的工作.它没有返回任何错误或做任何新的事情,就像所有.它甚至被设置为'当前项目',所以当我运行我的项目时,它应该做些不同的事情吗?我相信问题的一部分是我的根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");
    }
}
Run Code Online (Sandbox Code Playgroud)

And I always got:

1

Extra Line here

2

As the output. If I removed the 'move cursor up' ANSI println statement attempt I got:

1

2

What I wanted was:

2

1

(the whole point being, I'm able to move up a line freely)

I've also tried making them print statements and that didn't work either.

So I'm now at wits end

So here is what I want, an answer something like:

  1. A nonintrusive way to change the setting for cmd.exe to allow child applications like java to use ANSI BY DEFAULT when ran

  2. OR a nonintrusive library that doesn't reuqire maven and a million other things to enable ANSI so I can run the ANSI in java in console and get my desired output

  3. OR a programatic workaround that allows me to effectively print one line up without this whole ANSI thing

  4. OR help configuring IntelliJ console so that I can actually use a different console and use ANSI to print one line up

To address the obvious concerns

Since 1 and 4 are superuser questions and 2 is 'I need a library' and offtopic I'm more talking about point 3 here. If there is no workaround for this and the answer is one of the offtopic ones just tell me there is no workaround. I don't know how else to ask this question since it is a 'programming specific problem' it just has many solutions some of which are not 'on topic' because they aren't programming solutions. If the only answer is 'the solution isn't on topic here' then I'll go ask in the appropriate place. Let me know if I should delete this question when I go to ask it somewhere else.

What I think might work for ontopic part of this

Since 3 is on topic here I'll discuss what I'm thinking:

Maybe I could make some sort of system to print only to certain arrays instead of moving up and down lines (i.e. have an array to represent the lines, traverse the tree and instead of moving up and down lines, just switching the array to print to). I don't see this as very efficient and Its kindof a waste of arrays and processing power but if its a solution I'm willing to hear it. Thats all I can 'think of' but most of what I've tried is trying to get ANSI to work.

For future reference:

what is the appropriate way to ask these questions with multiple off topic solutions/ solution questions? Is it better just not to ask them at all? Do solutions that involve questions consitute a chameleon question? I don't feel like bringing the meta effect upon myself.

Edit 1: where I'm at so far:

I've tried the whole git bash thing again and boy was it a process. The actual git bash path in the terminal needs to be in quotes with the --login -i arguments coming after wards. Ex:

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

This setting is for the java terminal. THEN you have to set a windows environment variable named PATH to your java jdk. Go to your path environment variables (there are a million and one youtube videos for that) and set a new vairable named PATH to your jdk. Ex:

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

This question:

How can i make gitbash find the javac command?

Goes through that process extensively

Tl;dr You have to set a windows path variable this in order for git bash to recognize the javac and java commands.

Once thats done you need to actually run your java and javac commands like you would in any terminal. BTW be careful because paths in git bash require a two '\' notation instead of the normal '\' so your source directory path might look like this:

C:\IdeaProjects\Calculator\src\

Then you just run:

javac ClassName.java

java ClassName

BUT THEN it doesn't actually print the ANSI output, it prints the raw escape characters. Also, I found out I was using the WRONG escape sequence (I had the wrong number to represent the 'esc' button since the 'esc' key is represented as some number, but I had the wrong hex number I was using like x330 or something). I also learned that the notation is like this:

'esc key hex number' + '[' + 'parameter hex values seperated by commas'

so this might look like:

\x1B [ A

where the actual letters and numbers are hex value stuff (without the obvious 0x...) and the first escape hex value has an x in it (why?). Anyways, when running them in java as strings you need to escape the escape character (duh right?) with an extra '\' so for example the code might look like:

System.out.println("\\\x1B [A");
Run Code Online (Sandbox Code Playgroud)

I just noticed that stack overflow escapes these too so I actually have three '\' but for you guys it only displays two '\', weird right? Anyways back to what I was saying

BUT STILL the output doesn't actually work! This is where I'm at. I've done the above and I 99.9% know git bash is installed right and runs fine but when I run this:

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

I get this in java console (not git bash??):

1

\x1B [A

2

and this in git bash:

1

\x1B [A

2

What I actually want is:

2

1

Because the ANSI escape character is supposed to move my cursor/linefeed/whatever, one line upwards. The same thing happens if I run the above code but instead use the ANSI code: "\x1B [F". Only raw ANSI is output. I'm pretty sure git bash was suppsoed to be 'natively ANSI aware' and I've seen people say that on websites so I don't know why it isn't working.

And I still don't know for sure if those are two seperate console outputs, or the same console output. I really can't tell so if anyone wants to leave a comment saying 'yeah its the same dummy', I'd appreciate it because I can't find a definitive source out on the web that it is. I think it is but nothing other than the console setting in intelliJ indicates that as true.

I've heard rumors of a TERM variable that needs to be set or otherwise manipulated on windows. I've checked myself what it is using:

echo $TERM

in git bash and I got back:

cygwin

So I don't exactly know if thats good or bad because I've literally gone through all the search terms you can think of and they all lead to the same basic page of results for 'git bash colors not working' and most of them involve windows 7 (don't have it) installing maven/jansi (don't want or shouldn't need it) or some other language that isn't java and using some other IDE which isn't IntelliJ. Some pages that do have my specific requirements have said something about TERM suppsoed to be xterm or some other thing like xterm-256 or something for 'color' output, something like this. I am so unfamiliar with this stuff so I don't even know where to begin.

Too long give us a tl;dr

I need to know why git bash is printing raw ANSI instead of actually using the ANSI.

what I know

I'm using git bash with IntelliJ, 99.9% sure I have my path set correctly, I am able to run my java class from git bash, I have it set as the IntelliJ terminal and I currently have the windows TERM variable set to cygwin.

What I don't know

I don't know what TERM needs to be and can't find it on the web, I can't tell if the IntelliJ console that appears when I click the green arrow 'run' is the same as the git bash console, and I can't figure out if some other thing is preventing me from actually interpreting the ANSI.

What I need

I need a simple explanation, something straight out of r/ELI5 of what is wrong with git bash if anything and how to fix it. If it can't be explained simply or nothing is wrong then maybe I'll try another supposedly 'natively ANSI aware' terminal. I think Powershell was another option that was listed. My best bet is that the TERM variable needs to be something else, or git bash was never really natively ANSI aware and capable to begin with. I've seen other questions with the same problem for colors but their fixes are for older versions/different languages and things or they don't actually work. I have yet to find a good page for 'git bash outputs raw ANSI in intelliJ' and I've used variations of those exact words for hours now. All I can get is long github discussions on the 'bugs' related to this and they confuse me, don't lead to solutions, and may be active or just don't contain any resolution.

Edit 2

After doing some more research I've learned that my previous escape code was correct:

\033[A

\x1B[A

should be similar.

I also learned that it isn't the console I'm using thats the problem, its Windows itself. I now know this because I've tried compiling and running on cmd.exe , git bash and powershell. To change the default setting talked about earlier (consoles not supporting ansi for child applications) you have to EXPLICITLY enable it via the program itself rather than rely on a console or something.

link to a question that explains this in Python here:

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

tl;dr

The method that they use is something called getConsoleMode and setConsoleMode and VIRTUALTERMINALPROCESSING flags. Apparently you need to use these to actually set the console mode to support ANSI. I don't currently know if those are things that are in java hidden somewhere or (likely) something that needs to be added to the base java libraries. I'm going to try and figure out how they actually get the ctypes thing from that question (seems to be what they're importing to sue these methods) and get the methods I need. Once I do I'll post that as an answer unless one of you figures it out before I do and can explain it better.

Apparently the escape sequences work fine if you only use them from console but If you use a "child application" then they don't work. So at the very least we now for sure know the root cause of the problem.

Edit 3

Found this which is highly relevant especially the console virtual terminal sequences section (lefthand navbar):

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

This which, near the bottom has a whole C-implementation of how to enable the console to read ANSI. Apparently this doesn't need libraries at all but the process to actually change the console defaults to use code like this requires sysadmin privileges, intimate knowledge of the program files and a whole host of other things (at least if you're before the windows 10 update when color support was changed). Now its still disabled by default but can be enabled. I don't yet know how to try ANSI from the console directly. Ive tried multiple

echo \x1B[(insert ANSI code here)

but none of the commands seem to work in ANY terminal (cmd, git bash, powershell). They just return the raw code

\x1B[(whatever the ANSI code was)

I obviously am new to the console so I might be using the wrong command, if so feel free to enlighten me but the examples I've seen use echo. ANYWAYS, I thought that calling the ANSI directly from terminal was supposed to work since its supposedly enabled by default just not child applications (post windows 10 update) BUT maybe its not, maybe its disabled by default and even when enabled its still disabled for child applications (java) unless explicitly changed in said child application (java). I'm going to try to see if its possible to enable ANSI directly from console, or if the linked C-code needs to be directly ported to java or ran in console just to work. The problem is I don't know how to get the imports/includes that the C-code uses and use it for code in java. I'd rather not just accept a coded 'solution' in C and try and use that alongside java code, I'd rather translate, understand it better and have my own code that does the same thing.

Another option I've been told is something called ANSICON which is like some sort of plugin that you install in the console with the -i flag and thats suppsoed to enable ANSI at least in-console. I found this

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

the above explains that process in a little more detail.

My specific windows version and the version of the update

Another thing I learned was that the specific version of windows 10 that the 'update' that changed ANSI console behavior was like windows 10 v1151 or something, I'll try and find the webpage to source this directly but I currently have windows 10 v1607 so I think I should be good. Included in that was the actual OS build which I have 14393.2035 and I think that was identified as a particularly intermiediate update to this process in one of my previous links (I believe its the one with the whole github discussion about the update, you can find it here: https://github.com/Microsoft/WSL/issues/1173). I have a work computer so I can't really make system updates because I'm not an administrator and I doubt IT would let an intern go around updating work computers.

Anyways, I'll continue on trying to see if I can get the C-code to java, I'll test it and then try and post an answer. If ya'll are ahead of me let me know.

Ale*_*ros 1

您在“编辑2”( /sf/answers/2573261701/ )中引用的python方式只是调用Windows特定的本机代码(kernel32,不可移植)来“修复”此问题。

我想你对此很满意,并且想在 Java 中做同样的事情(即当你检测到 Windows 时调用 kernel32)...

JNA 是一个非常轻量级的Java 库,它具有针对 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 个(或 2 个,如果添加 jna-platform)具有非常特定范围的 jar(执行本机调用,无需所有 JNI 准备开销)就足够轻量了。您不需要生成任何标头,也不需要在编译过程中更改任何内容。只需将这些 jar 添加到类路径即可工作。

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