强制StandardOutputEncoding为UTF8

Mah*_*dsi 5 .net encoding process utf-8

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

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

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

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

我知道此时的假设是我正在解析的输出的应用程序根本就不发送UTF8输出,但是当我尝试将应用程序的输出从命令行转储到文件后绝对不是这种情况.强制命令提示的代码页为65001,一切看起来都很好.

chcp 65001 && slave.exe > file.txt
Run Code Online (Sandbox Code Playgroud)

通过这个,我知道应用程序slave.txt能够吐出UTF8编码的标准输出,但是尽可能地尝试,我无法让StandardOutputEncoding在我的C#应用​​程序中做同样的事情.

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

Mah*_*dsi 5

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

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

因此,我编写了一个名为UtfRedirect的代理应用程序,我在GitHub上根据MIT许可证的条款发布了源代码,该代码旨在在.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();
Run Code Online (Sandbox Code Playgroud)