我正在寻找从我的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编码的文本文件中,但我现在暂时不采取这种方法。
答案 0 :(得分:5)
StandardOutputEncoding对执行的应用程序的stdout没有任何影响的唯一影响。它唯一能做的就是设置StreamReader的编码,该编码位于从正在运行的应用程序捕获的二进制stdout流之上。
对于本机输出UTF8或Unicode标准输出的应用程序,这是可以的,但是大多数Microsoft实用程序不这样做,而只会根据控制台的代码页对结果进行编码。控制台的代码页是使用WIN32 API SetConsoleOutputCP
和SetConsoleCP
手动设置的,需要手动强制为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)