强制StandardOutputEncoding为UTF8

时间:2011-09-22 19:58:12

标签: .net encoding utf-8 process

我正在寻找从我的C#项目中另一个应用程序的标准输出流中解析UTF8字符。使用默认方法,从进程的标准输出流中读取时,ANSI范围之外的字符会被破坏。

现在根据微软的说法,我需要做的是设置StandardOutputEncoding:

  

如果StandardOutputEncoding属性的值为Nothing,则进程将使用标准输出的默认标准输出编码。必须在启动进程之前设置StandardOutputEncoding属性。设置此属性不保证进程将使用指定的编码。应测试应用程序以确定该过程支持的编码。

但是,尝试将StandardOutputEncoding设置为UTF8 / CP65001,输出为read,当转储到二进制文件时,显示相同的外语字符阉割。它们总是被读作'?' (又名0x3F)而不是它们应该是什么。

我知道此时的假设是我正在解析的输出的应用程序根本就不发送UTF8输出,但是当我尝试将应用程序的输出转储到文件时,情况肯定不是这样的。将命令提示的代码页强制为65001后,命令行一切正常。

chcp 65001 && slave.exe > file.txt

通过这个,我知道应用程序slave.txt能够吐出UTF8编码的标准输出,但尽可能地尝试,我无法让StandardOutputEncoding在我的C#应用​​程序中执行相同操作。

每次我最终都在处理.NET中的编码时,我希望我回到C ++世界,一切都需要更多的工作,但是更加透明。我正在考虑编写一个C应用程序来将slave.txt的输出读入一个准备好进行C#解析的UTF8编码的文本文件中,但我现在暂时不采取这种方法。

2 个答案:

答案 0 :(得分:5)

StandardOutputEncoding对执行的应用程序的stdout没有任何影响的唯一影响。它唯一能做的就是设置StreamReader的编码,该编码位于从正在运行的应用程序捕获的二进制stdout流之上。

对于本机输出UTF8或Unicode标准输出的应用程序,这是可以的,但是大多数Microsoft实用程序这样做,而只会根据控制台的代码页对结果进行编码。控制台的代码页是使用WIN32 API SetConsoleOutputCPSetConsoleCP手动设置的,需要手动强制为UTF8,如果这是您想要阅读的内容。这需要在执行exe的控制台上完成,据我所知,无法从主机的.NET环境中完成。

因此,我编写了一个名为UtfRedirect的代理应用程序,我根据MIT许可证条款发布了on GitHub的源代码,该许可证旨在在.NET主机中生成,然后告知哪个exe执行。它将设置最终slave exe控制台的代码页,然后运行它并将stdout传回主机。

示例UtfRedirector调用:

//At the time of creating the process:
_process = new Process
                {
                    StartInfo =
                        {
                            FileName = application,
                            Arguments = arguments,
                            RedirectStandardInput = true,
                            RedirectStandardOutput = true,
                            StandardOutputEncoding = Encoding.UTF8,
                            StandardErrorEncoding =  Encoding.UTF8,
                            UseShellExecute = false,
                        },
                };

_process.StartInfo.Arguments = "";
_process.StartInfo.FileName = "UtfRedirect.exe"

//At the time of running the process
_process.Start();

//Write the name of the final slave exe to the stdin of UtfRedirector in UTF8
var bytes = Encoding.UTF8.GetBytes(application);
_process.StandardInput.BaseStream.Write(bytes, 0, bytes.Length);
_process.StandardInput.WriteLine();

//Write the arguments to be sent to the final slave exe to the stdin of UtfRedirector in UTF8
bytes = Encoding.UTF8.GetBytes(arguments);
_process.StandardInput.BaseStream.Write(bytes, 0, bytes.Length);
_process.StandardInput.WriteLine();

//Read the output that has been proxied with a forced codepage of UTF8
string utf8Output = _process.StandardOutput.ReadToEnd();

答案 1 :(得分:0)

现代.NET选项:

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

Source