Search code examples
javawindowsterminalencodingutf-8

Issues printing emojis and symbols on Windows Terminal using Java


I'm using JDK 21, that has the file.encoding automatically to UTF-8 but, even adding it explicitly as a command argument, nothing changes. I checked the property in the code and it is indeed UTF-8.

I've set sun.stdout.encoding to UTF-8 manually too. It changes the output, but still unreadable.

Printing the emoji 🤣 on System.out with the sun.stdout the result is -fñú and without it, it just shows a ?

On another post I saw people suggesting to change the terminal code page or use the System.console().writer instead of System.out, but neither worked for me

The source is being encoded with UTF-8 properly too

  • JDK 21
  • Windows 11
  • Windows Terminal - Powershell

Solution

  • Introduction

    After several days of research, I found two ways to enable UTF-8 support in Java console applications:

    • Using JLine3 with JNI (Recommended)
    • Executing specific terminal commands before starting your console application

    JLine3

    JLine is a library designed to enhance the terminal experience in Java, providing support for features that previously required native code. One of the cases where this applies is UTF-8 support.

    The JLine library includes a class called Terminal, which provides a PrintWriter accessible through the writer() method. This implementation automatically supports UTF-8 for any terminal compatible with the library, making it the best solution I found.

    Maven Dependencies

    To use JLine on Windows, you may need to include the JNI dependency. For those using Maven, here are the dependencies I'm using on pom.xml, but the most import are jline-terminal and jline-terminal-jni:

    <!-- https://mvnrepository.com/artifact/org.jline/jline-terminal -->
            <dependency>
                <groupId>org.jline</groupId>
                <artifactId>jline-terminal</artifactId>
                <version>${jline.bundle.version}</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.jline/jline-terminal-jni -->
            <dependency>
                <groupId>org.jline</groupId>
                <artifactId>jline-terminal-jni</artifactId>
                <version>${jline.bundle.version}</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.jline/jline-native -->
            <dependency>
                <groupId>org.jline</groupId>
                <artifactId>jline-native</artifactId>
                <version>${jline.bundle.version}</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.jline/jline-console -->
            <dependency>
                <groupId>org.jline</groupId>
                <artifactId>jline-console</artifactId>
                <version>${jline.bundle.version}</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.jline/jline-style -->
            <dependency>
                <groupId>org.jline</groupId>
                <artifactId>jline-style</artifactId>
                <version>${jline.bundle.version}</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.jline/jline-reader -->
            <dependency>
                <groupId>org.jline</groupId>
                <artifactId>jline-reader</artifactId>
                <version>${jline.bundle.version}</version>
            </dependency>
    

    Terminal Commands

    Depending on the terminal you are using, there are different commands you can execute before starting your application to enable UTF-8 support on Windows. For example, as mentioned by some users in the comments:

    • Powershell
    [Console]::InputEncoding = [Console]::OutputEncoding = New-Object System.Text.UTF8Encoding
    
    • CMD
    chcp 65001
    

    By using these methods, you can ensure that your Java console application handles UTF-8 characters correctly.

    Note

    If it doesn't work, in older versions of Java the file.encoding flag wasn't set to UTF-8 by default, so you can try running your application setting it to UTF-8 and checking if it gives you the correct result:

    java -Dfile.encoding=UTF-8 MyApp