如何在 C# 中更改进程标准输入的编码?



我正在尝试用C#编写进程(C++程序)的标准输入。问题是C++程序似乎无法读取我从C#应用程序中编写的内容。以下是两个程序:

// C#
static void Main(string[] args) {
Console.InputEncoding = Encoding.Unicode;
Console.OutputEncoding = Encoding.Unicode;
Process CoutN = new Process();
CoutN.StartInfo.FileName = @"C:UsersVeskDesktopCoutN.exe";
CoutN.StartInfo.UseShellExecute = false;
CoutN.StartInfo.RedirectStandardInput = true;
CoutN.StartInfo.RedirectStandardOutput = false;
CoutN.Start();
CoutN.StandardInput.WriteLine("5");
CoutN.WaitForExit();
Console.ReadKey();
}
// C++
int main() {
int n;
std::cin >> n;
std::cout << "N is " << n << std::endl;
return 0;
}

这是我的C#程序的输出:N is 0。它应该是N is 5

据我所知,C#用于进程的输入/输出流的编码与控制台使用的编码相同。不过,在我的C#程序中,我需要能够使用控制台输入cyrillic文本(以及其他非ASCII文本)。唯一适用于此的控制台编码是Encoding.Unicode(显然只是UTF-16 LE)。

但是,当我试图写入进程的输入流时,它似乎无法理解这一点,并且出于某种原因,它输出了N is 0。据我所知,这是因为UTF-16与ASCII不兼容(或者C++iostream所期望的)。

那么,有没有一种方法可以真正更改流程的标准输入所使用的编码

以下是我尝试过/无法尝试的内容:

  • 我不想更改控制台的编码,因为我计划以异步运行的方法运行进程,并且我希望仍然能够与C#程序接口,所以我担心它会把事情搞砸,即使我只是更改了编码,只是在写入进程时,然后再次更改它
  • 我知道C++程序可能会被更改,以便它可以读取UTF-16,但我不想这样做,因为我的C#程序必须能够运行并"读取";接口";用简单的iostream(cincout)编写各种C++程序。(编辑以澄清:我的C#程序只需要向C++程序"发送"ASCII文本)
  • 我确实尝试过将控制台的编码更改为Encoding.ASCII,并且成功了。如果我只是将控制台留在它的默认编码位置,它也会起作用。但同样,这对我来说不起作用,因为这些编码似乎不适用于西里尔文
  • 我尝试将控制台的输入编码设置为Encoding.UTF8,但没有成功,尽管我无论如何都无法使用它,因为它似乎不适用于我的C#应用程序中的西里尔文
  • 我试图更改CoutN.StandardInput.Encoding,但不幸的是它是只读属性
  • 我还试图重定向标准输出,只是想看看它是否有效,奇怪的是,它确实有效。我只需要使用CoutN.StandardOutput.ReadToEnd(),它就可以工作,C++程序的输出也可以正确读取(不过仍然显示N is 0)。但由于某些原因,标准输入不同
  • 我试着不重定向标准输入,又一次只是为了看看它是否有效,但又一次非常奇怪!。我刚刚在C#程序的控制台中编写了5,结果是N is 5
  • 我尝试创建一个具有不同编码的StreamWriter,并从中写入:
StreamWriter str = new StreamWriter(CoutN.StandardInput.BaseStream, Encoding.ASCII);
str.WriteLine("5");

但这也没用。我甚至尝试了基本上所有的编码,甚至没有编码,但什么都不起作用。

  • 我试着自己给BaseStream写信:
byte[] buffer = Encoding.ASCII.GetBytes("5");
CoutN.StandardInput.BaseStream.Write(buffer, 0, buffer.Length);
CoutN.StandardInput.WriteLine();

但这并没有奏效。

在这一点上,我觉得我已经用尽了所有可以尝试的选择。感谢您的帮助,提前感谢

您无法从自己的代码中选择其他进程正在使用的编码-如果您将输入发送到期望特定编码的应用程序的标准输入流,那么除了更改一些设置之外,您对此无能为力。

如果您正在与另一个应用程序的STDIO流交互,那么您应该匹配它所期望的任何编码,而不是相反。控制台的编码其实并不重要,除非应用程序从环境中继承其编码。

事实上,如果您试图使用支持西里尔字母的编码,那么接收应用程序的设计必须能够适应这种情况。如果应用程序是由一个母语字符集只使用拉丁字符的人编写的,那么他们很可能从来没有这么做过。这也是推动在所有地方采用UTF8的部分原因,从那时起,你真的不需要想太多。

编辑:如果你试图匹配预期的输入编码,那么你就这样做:

Process.StandardInput.Write(Encoding.ASCII.GetBytes("My String Herern"));

Encoding.ASCII替换为适用的任何字符集,以获得适当的GetBytes()方法。

请注意,ASCII字符集特别不包括西里尔字母,因此不可能在需要ASCII的应用程序中使用它们。如果它需要其他一些支持它们的字符集,那么你就可以了。西里尔文使用代码页855或需要UTF8。

最新更新