在C#控制台应用程序中输入非英文字符的问题

6

我正在尝试在英文Windows 7 Ultimate 64位上使用Visual Studio 2010构建控制台C#应用程序。当我尝试复制包含非ASCII字符的路径并将其粘贴到我的控制台应用程序中时,非ASCII字符会变成???. 有没有办法解决这个问题?

这是我要复制的内容:C:\Test Folder\документи

这是代码(按照上面建议的链接):

Console.OutputEncoding = System.Text.Encoding.UTF8;
string strLineUserInput = Console.ReadLine();

即使我改变字体,当我用调试器测试时,C:\Test Folder\документиstrLineUserInput 变量中仍然变成了 C:\Test Folder\?????????

还要注意,与“重复帖子”链接不同,我需要这些字符作为输入。

所以如果我这样做:

Console.InputEncoding = System.Text.Encoding.UTF8;
string strLineUserInput = Console.ReadLine();

如果我读取上面的文字,strLineUserInput会变成null


是的,请前往控制台窗口设置并更改字体为支持扩展字符的字体。Lucida控制台应该可以。 - Wiktor Zychla
3
可能是 如何将 Unicode 字符写入控制台? 的重复问题。 - Jeremy Thompson
你能澄清一下你要把这些字符粘贴到哪里吗?也就是说,它是要进入你的C#源代码中,还是在应用程序运行时作为输入进入控制台窗口? - Stephen Quan
@JeremyThompson 这并不完全是重复,但足够接近。 - Nik Bougalis
1
@c00000fd - 告诉我们为什么可能的重复问题对你没有帮助,这将有助于减少重复指控。 - System Down
显示剩余4条评论
5个回答

6

请按照以下步骤进行:

  1. Change the console window font to Lucida Console for both when debugging / not debugging.
  2. Execute the following code:

    public static void Main(String[] args)
    {
        Console.OutputEncoding = System.Text.Encoding.GetEncoding("Cyrillic");
        Console.InputEncoding = System.Text.Encoding.GetEncoding("Cyrillic");
    
        Console.WriteLine(@"C:\Test Folder\документи");
        // input C:\Test Folder\документи
        string strLineUserInput = Console.ReadLine();
        Console.WriteLine(strLineUserInput);
    }
    
输出结果应为:
C:\Test Folder\документи
C:\Test Folder\документи
C:\Test Folder\документи

[更新]

也许你想要使用ReadKey方法使其工作(你仍然需要使用Lucida Console字体):

static void Main(string[] args)
{
    Console.OutputEncoding = Encoding.UTF8;
    Console.InputEncoding = Encoding.UTF8;

    string s = @"C:\Test Folder\документи";
    Console.WriteLine(s);

    // input C:\Test Folder\документи
    var strInput = ReadLineUTF();

    Console.WriteLine(strInput);
}

static string ReadLineUTF()
{
    ConsoleKeyInfo currentKey;

    var sBuilder = new StringBuilder();
    do
    {
        currentKey = Console.ReadKey();
        // avoid capturing newline
        if (currentKey.Key != ConsoleKey.Enter)
            sBuilder.Append(currentKey.KeyChar);

    }
    // check if Enter was pressed
    while (currentKey.Key != ConsoleKey.Enter);

    // move on the next line
    Console.WriteLine();

    return sBuilder.ToString();
}

我在 Console.OutputEncoding = System.Text.Encoding.Unicode 这一行上遇到了 System.IO.IOException: 参数不正确。 的错误。 - c00000fd
再次强调,应该使用UTF-8编码。我只是举了一个西里尔字母的例子来测试。 - c00000fd

3
以下代码对我有帮助。请使用 Encoding.Unicode 替代 Encoding.UTF8。
  Console.OutputEncoding = Console.InputEncoding = Encoding.Unicode;
  Console.Write("Введите свое имя: ");
  string name = Console.ReadLine(); 
  Console.WriteLine($"Привет {name}"); 

0

你的文本看起来像是俄语。

文件资源管理器采用Unicode编码。

控制台应用程序可能不采用Unicode编码。

当你将Unicode字符粘贴到控制台窗口时,它们会根据当前系统区域设置转换为非Unicode系统。如果你的系统区域设置不支持俄语,则这些字符将转换为“?”。

尝试查看你的控制面板>区域和语言设置:

  1. 打开控制面板
  2. 选择区域和语言
  3. 查看非Unicode的当前语言
  4. 如果没有设置为俄语,请尝试“更改系统区域设置”并将其设置为俄语。

我不知道这是什么语言。我只是为了测试目的使用了谷歌翻译。控制台应用程序不应该作为Unicode构建,并在技术上支持任何字符集,而不受系统语言设置的影响吗? - c00000fd
并非所有的应用程序都是Unicode编码的。设置系统区域设置适用于非Unicode应用程序。出现“?”的情况表明您的应用程序的行为类似于非Unicode应用程序。 - Stephen Quan
我知道不是所有的人都这样,但我应该能够控制我想要构建我的方式——Unicode还是ASCII。 - c00000fd

0

这似乎对于C#来说有些过度,但它对我起作用了:

using System.Runtime.InteropServices;

[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr GetStdHandle(int nStdHandle);

[DllImport("kernel32.dll")]
static extern bool ReadConsoleW(IntPtr hConsoleInput, [Out] byte[]
    lpBuffer, uint nNumberOfCharsToRead, out uint lpNumberOfCharsRead,
    IntPtr lpReserved);

public static IntPtr GetWin32InputHandle()
{
    const int STD_INPUT_HANDLE = -10;
    IntPtr inHandle = GetStdHandle(STD_INPUT_HANDLE);
    return inHandle;
}

public static string ReadInputLineAsUTF8()
{
    //I can't seem to find a way not to hardcode the size here???
    const int bufferSize = 1024 * 2;
    byte[] buffer = new byte[bufferSize];

    uint charsRead = 0;
    ReadConsoleW(GetWin32InputHandle(), buffer, bufferSize, out charsRead, (IntPtr)0);

    //Make new array of data read
    byte[] buffer2 = new byte[charsRead * 2];
    for (int i = 0; i < charsRead * 2; i++)
    {
        buffer2[i] = buffer[i];
    }

    //Convert string to UTF-8
    return Encoding.UTF8.GetString(Encoding.Convert(Encoding.Unicode, Encoding.UTF8, buffer2)).Trim();
}

-1

如果你只想将输入复制粘贴到文本框中,这非常容易。 在您的应用程序中使用复选框控件,您可以编写代码来更改字体,例如:

enter code here
 private void checkBox1_CheckedChanged(object sender, EventArgs e)
    {
        if (checkBox1.Checked)
        {
            textBox1.Font = new Font("Your font", 10);
        }
        else 
        {
            textBox1.Font = new Font("Times New Roman", 10);
        }
    }

或者,如果您经常粘贴非英语文本,则可以更改文本框的字体属性。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接