ucag
ucag

Reputation: 477

How to show emoji in c# console output?

I have a problem in output emoji in console.

String starts with Unicode flag "\u" works well, like "\u263A".

However, if just simply copy and paste an emoji into string, like "🎁", it does not work.

code test below:

using System;
using System.Text;

namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {

            Console.OutputEncoding = Encoding.UTF8;
            string s1 = "🎁";
            string s1_uni = "\ud83c\udf81"; // unicode code for s1
            string s2 = "☺";
            string s2_uni = "\u263A"; // unicode code for s2
            Console.WriteLine(s1);
            Console.WriteLine(s1_uni);
            Console.WriteLine(s2);
            Console.WriteLine(s2_uni);
            Console.ReadLine();
        }
    }
}

s1 and s1_uni can successfully be outputted while s2 and s2_uni failed.

I want to know how to fix this problem.

By the way, the font applied is 'Consolas', which works perfectly in Visual Studio.enter image description here

Update:

Please note that, I've done some searches in stackoverflow before I present this question. The most common way is to set the Console encoding to utf-8, which is done in the first line of Main.

This way (Console.OutputEncoding = Encoding.UTF8) can not totally fit the situation I presented.

Also, the reason why I make supplement to the console font in the question is to declare that Consolas font works perfectly in showing emoji in VS but failed in console. The first emoji failed to show.

Please do not close this question. Thanks.

Update2:

this emoji can be shown in the VS terminal.

enter image description here

Update3:

Thank Peter Duniho for help. And you are right.

While we are discussing, I look through the document MS Unicode Support for the Console.

Display of characters outside the Basic Multilingual Plane (that is, of surrogate pairs) is not supported, even if they are defined in a linked font file.

Code point of the emoji can't be shown in the console is just outside the BMP. And console does not support show code point outside BMP. Therefore, this emoji is not shown.

To change running context which may support this emoji. I did some experiments.

CMD: enter image description here

Power Shell: enter image description here

Windows Terminal: enter image description here

You can see, windows terminal supports it.

Strictly speaking, the problem I met is not a duplicate question in stackoverflow. Because my code just did whatever can be done to meet the requirement. The problem is the running context, not code.

Thank Peter Duniho for help.

Upvotes: 13

Views: 22520

Answers (2)

Tore Aurstad
Tore Aurstad

Reputation: 3816

As already noted, using Windows Terminal and setting UTF-8 output encoding displays emojis, at least those supported. Also, consider another font such as using "CaskaydiaCove Nerd font Mono", available for download from Github as a release and you can doubleclick on the extracted fonts inside the ttf Truetype font to install the font and switch font via "Appearance" in Windows Terminal, make sure you select the correct shell.

Here is a small console app I made to display emojis and their unicode range appended. It shows which emojis we have available and how we programatically can output emojis inside ranges of relevant emoji code points.

using System.Text;

Console.OutputEncoding = System.Text.Encoding.UTF8;

var sb = new StringBuilder();
int emojisAdded = 0;
const int EMOJIS_PER_LINE = 10;
int codePoint = 0x1F300;

// Define the ranges of emojis
int[][] emojiRanges = new int[][]
{
            new int[] { 0x1F300, 0x1F5FF },
            new int[] { 0x1F600, 0x1F64F },
            new int[] { 0x1F680, 0x1F6FF },
            new int[] { 0x1F900, 0x1F9FF },
            new int[] { 0x1FA70, 0x1FAFF }
};

foreach (var emojiRange in emojiRanges)
{

    for (codePoint = emojiRange[0]; codePoint <= emojiRange[1]; codePoint++)
    {
        string emoji = char.ConvertFromUtf32(codePoint);
        sb.Append(emoji);
        emojisAdded++;
        if (emojisAdded % EMOJIS_PER_LINE == 0)
        {
            Console.WriteLine($"{sb.ToString()} {codePoint - 9:X}- {codePoint:X}");
            sb.Clear();
        }
    }

    Console.WriteLine(sb.ToString() + " " + (codePoint - 9).ToString("X") + (codePoint.ToString("X"))); //print remaining emojis

}

If we compile the program and open it in Windows Terminal, you should get something similar to what shown below.

Emoji in Powershell - Windows Terminal - Using Cascadia NF font Some emojis still not rendering

I see there are issues on the very last emojis as they are not outputted correct, in the group "Symbols and Pictographs Extended-A".

  • Emoticons: U+1F600 to U+1F64F
  • Miscellaneous Symbols and Pictographs: U+1F300 to U+1F5FF
  • Transport and Map Symbols: U+1F680 to U+1F6FF
  • Supplemental Symbols and Pictographs: U+1F900 to U+1F9FF
  • Symbols and Pictographs Extended-A: U+1FA70 to U+1FAFF

Upvotes: 1

Peter Duniho
Peter Duniho

Reputation: 70661

The current Windows command line console, cmd.exe, still uses GDI+ to render text. And the GDI+ API it uses does not correctly handle combining/surrogate pair characters like the emoji you want to display.

This is true even when using a font that includes the glyph for the character you want, and even when you have correctly set the output encoding for the Console class to a Unicode encoding (both of which you've done in your example).

Microsoft appears to be working on improvements to the command prompt code, to upgrade it to use the DirectWrite API instead of GDI+. If and when these improvements are released, the console window should be able to display your emoji correctly. See Github issue UTF-8 rendering woes #75

In the meantime, you can run your program in a context that is able to render these characters correctly, such as Windows Terminal or PowerShell.

Additional details regarding the limitations of the GDI+ font rendering can be found in Github issues Add emoji support to Windows Console #190 and emoji/unicode support mostly broken in windows #2693 (the latter isn't about a Windows component per se, but still relates to this problem).

Upvotes: 10

Related Questions