Reputation: 477
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.
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.
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.
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
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.
I see there are issues on the very last emojis as they are not outputted correct, in the group "Symbols and Pictographs Extended-A".
Upvotes: 1
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