0

I wanted to Print Colored Text in Java Console. I have Ran the following code in VSCode and it Runs fine and its not working in CMD.

The java Code: `

    
// Java Program to Print Colored Text in Console
  
// Importing input output classes
import java.io.*;
  
// Main class
public class GFG {
  
    // Declaring ANSI_RESET so that we can reset the color
    public static final String ANSI_RESET = "\u001B[0m";
  
    // Declaring the color
    // Custom declaration
    public static final String ANSI_YELLOW = "\u001B[33m";
  
    // Main driver method
    public static void main(String[] args)
    {
        // Printing the text on console prior adding
        // the desired color
        System.out.println(ANSI_YELLOW + "This text is yellow" + ANSI_RESET);
    }
}

    

`
Source: https://www.geeksforgeeks.org/how-to-print-colored-text-in-java-console/

Running the code in windows CMD terminal it shows:

D:\CodeSpaceOfline\sudocu>java sudoco.java  
  ←[31mThis text is yellow←[0m`
Annas
  • 11
  • Yes, that's not surprising. I don't think that's supported anymore. You might get on better in Powershell (it *can* do colour) but it might use a different mechanism – g00se Nov 04 '22 at 15:56
  • 2
    ANSI support in Windows is only enabled if the executable has been marked with a special flag or the program actively calls a dedicated operating system function to enable the support. Neither applies to the standard `java.exe`. The linked article also doesn’t mention that this support only exists in Windows 10 version 1511 or newer. It simply ran the example in IntelliJ, most probably, and never tried a CMD terminal. – Holger Nov 04 '22 at 17:27
  • Look on the results of the Stack Overflow search [[java\] Windows console output color*](https://stackoverflow.com/search?q=%5Bjava%5D+Windows+console+output+color*). For getting more knowledge about the Windows console read the Microsoft documentations [Classic Console APIs versus Virtual Terminal Sequences](https://learn.microsoft.com/en-us/windows/console/classic-vs-vt) and [Console Functions](https://learn.microsoft.com/en-us/windows/console/console-functions) and [Console Virtual Terminal Sequences](https://learn.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences). – Mofi Nov 04 '22 at 18:28

1 Answers1

3

ANSI support for the Windows CMD terminal is only available with Windows 10 version 1511 or newer. But even then, it’s not enable by default, for compatibility reasons. Native executables must have been marked as using ANSI or explicitly invoke a dedicated Windows function to enable ANSI support.

Neither applies to java.exe. Therefore, you don’t get ANSI support.

You could work-around this by delegating the printing to another software which has ANSI support enable, like the echo command.

import java.io.IOException;

public class ConsoleOutput {
    public static final String ANSI_RESET_ALL = "\33[0m";
    public static final String ANSI_YELLOW_FG = "\33[33m";
    public static final String ANSI_RESET_FG = "\33[39m";

    // Main driver method
    public static void main(String[] args) {
        // Printing the text on console prior adding
        // the desired color
        println(ANSI_YELLOW_FG + "This text is yellow" + ANSI_RESET_FG);
        println("This is normal color");
    }

    static void println(String s) {
        try {
            new ProcessBuilder("cmd", "/c", "echo " + s).inheritIO().start().waitFor();
        } catch (InterruptedException|IOException e) {
            throw new RuntimeException(e);
        }
    }
}

For large text fragments, you could dump them into a temporary file and use the type command to transfer them to the terminal.


Future Java versions will come with support to invoke native functions without the need for native helper code, like a JNI stub. With JDK 19’s preview version, the code to enable ANSI from within Java would look like

import java.lang.foreign.*;
import java.lang.invoke.*;

public class ConsoleOutput {
    public static final String ANSI_RESET_ALL = "\33[0m";
    public static final String ANSI_YELLOW_FG = "\33[33m";
    public static final String ANSI_RESET_FG = "\33[39m";

    public static void main(String[] args) {
        if(initANSI()) System.out.println("ANSI should now work");
        System.out.println(ANSI_YELLOW_FG + "This text is yellow" + ANSI_RESET_FG);
        System.out.println("This is normal color");
    }
    static boolean initANSI() {
        try {
            SymbolLookup sl = SymbolLookup.libraryLookup("kernel32.dll", MemorySession.global());
            Linker linker = Linker.nativeLinker();
            MethodHandle GetStdHandle = linker.downcallHandle(sl.lookup("GetStdHandle").get(),
                FunctionDescriptor.of(ValueLayout.ADDRESS, ValueLayout.JAVA_INT)
            );
            MethodHandle SetConsoleMode = linker.downcallHandle(sl.lookup("SetConsoleMode").get(),
                FunctionDescriptor.of(ValueLayout.JAVA_BOOLEAN, ValueLayout.ADDRESS, ValueLayout.JAVA_INT)
            );
            Addressable a = (MemoryAddress) GetStdHandle.invokeExact(STD_OUTPUT_HANDLE);
            return (boolean)SetConsoleMode.invokeExact(a,
                ENABLE_PROCESSED_OUTPUT|ENABLE_VIRTUAL_TERMINAL_PROCESSING);
        } catch (RuntimeException | Error unchecked) {
            throw unchecked;
        } catch(Throwable e) {
            throw new AssertionError(e);
        }
    }
    static final int STD_OUTPUT_HANDLE = -11,
        ENABLE_PROCESSED_OUTPUT = 0x0001, ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004;
}
Holger
  • 285,553
  • 42
  • 434
  • 765