简体   繁体   English

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

[英]How to change the encoding of a Process's Standard Input in C#?

I am trying to write to the Standard Input of a Process (a C++ program) in C#.我正在尝试在 C# 中写入进程的标准输入(C++ 程序)。 The problem is that the C++ program seems to not be able to read what I write from my C# app.问题是 C++ 程序似乎无法读取我从 C# 应用程序中写入的内容。 Here are both of the programs:以下是两个程序:

// C#
static void Main(string[] args) {
    Console.InputEncoding = Encoding.Unicode;
    Console.OutputEncoding = Encoding.Unicode;

    Process CoutN = new Process();
    CoutN.StartInfo.FileName = @"C:\Users\Vesk\Desktop\CoutN.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;
}

Here is the output from my C# program: N is 0 .这是我的 C# 程序中的 output : N is 0 It should instead be N is 5 .它应该是N is 5

From what I could understand the encoding that C# uses for a Process's Input/Output Stream is the same as the one used by the Console.据我了解,C# 用于进程输入/输出 Stream 的编码与控制台使用的编码相同。 Here's the thing though, in my C# program I'll need to be able to use the Console to input cyrillic text (as well as other non-ASCII text).但这就是问题所在,在我的 C# 程序中,我需要能够使用控制台输入西里尔文文本(以及其他非 ASCII 文本)。 The only Console Encoding which seems to work for that is Encoding.Unicode (which apparently is just UTF-16 LE).唯一似乎适用的控制台编码是Encoding.Unicode (显然只是 UTF-16 LE)。

But it seems that when I try to write to the Process's Input Stream, it just can't understand that and it outputs N is 0 for some reason.但似乎当我尝试写入进程的输入 Stream 时,它只是无法理解,并且由于某种原因它输出N is 0 From what I understand this is because UTF-16 is not compatible with ASCII (or whatever the C++ iostream expects).据我了解,这是因为 UTF-16 与 ASCII 不兼容(或任何 C++ iostream期望的)。

So is there a way to actually change the Encoding that the Process's Standard Input uses?那么有没有办法真正改变进程的标准输入使用的编码?

Here is what I have tried/cannot try:这是我尝试过/无法尝试的:

  • I don't want to change the Console's Encoding, because I plan on running the Process in an asynchronously running method and I want to still be able to interface with the C# program, so I fear that it will mess things up, even if I just change the Encoding, only while writing to the Process and then change it back again.我不想更改控制台的编码,因为我计划以异步运行的方法运行进程,并且我希望仍然能够与 C# 程序交互,所以我担心它会搞砸,即使我只需更改编码,仅在写入进程时再更改回来。
  • I know that the C++ program could probably be changed so that it can read UTF-16, but I don't want to do that since my C# program will have to be able to run and "interface" with all kinds of C++ programs, which use the simple iostream ( cin , cout ).我知道 C++ 程序可能会被更改,以便它可以读取 UTF-16,但我不想这样做,因为我的 C# 程序将必须能够运行并与各种 ZF6F87CF 程序、9FDCF8B3C3C2917它使用简单的iostream ( cin , cout )。 ( Edit for clarification: My C# program will only ever need to "send" ASCII text to the C++ program) 编辑澄清:我的 C# 程序只需要“发送”ASCII 文本到 C++ 程序)
  • I did try to Change the Console's Encoding to Encoding.ASCII and it worked.我确实尝试将控制台的编码更改为Encoding.ASCII并且它有效。 It also worked if I just left the Console at it's default Encoding.如果我只是将控制台保留为默认编码,它也可以工作。 But again this will not work for me, because these encodings don't seem to work with Cyrillic.但这又对我不起作用,因为这些编码似乎不适用于西里尔字母。
  • I tried setting the Console's Input Encoding to Encoding.UTF8 and that didn't work, although I wouldn't have been able to use that anyway, because it doesn't seem to work with Cyrillic text in my C# app.我尝试将控制台的输入编码设置为Encoding.UTF8但这不起作用,尽管无论如何我都无法使用它,因为它似乎不适用于我的 C# 应用程序中的西里尔文文本。
  • I tried to change CoutN.StandardInput.Encoding , but unfortunately it is a read-only property.我试图更改CoutN.StandardInput.Encoding ,但不幸的是它是一个只读属性。
  • I tried to also redirect the Standard Output, just to see if it works, and weirdly enough it does.我还尝试重定向标准 Output,只是为了看看它是否有效,而且奇怪的是它确实有效。 I can just use CoutN.StandardOutput.ReadToEnd() and it works and the output from the C++ program is read correctly (still says N is 0 though).我可以只使用CoutN.StandardOutput.ReadToEnd()并且它可以正常工作,并且 C++ 程序中的 output 被正确读取(尽管仍然说N is 0 )。 But for some reason the Standard Input is different.但由于某种原因,标准输入是不同的。
  • I tried to just not redirect the Standard Input, again just to see if it works, and again very weirdly it did.. I just wrote 5 in the C# program's Console and the output was N is 5 .我试图不重定向标准输入,再次只是为了看看它是否有效,而且非常奇怪的是它确实如此......我刚刚在 C# 程序的控制台中写了5 ,而 output 是N is 5
  • I tried to create a StreamWriter with a different encoding and write from there:我尝试创建一个具有不同编码的StreamWriter并从那里写入:
StreamWriter str = new StreamWriter(CoutN.StandardInput.BaseStream, Encoding.ASCII);
str.WriteLine("5");

But this didn't work either.但这也不起作用。 I even tried basically all the Encodings and even no Encoding, but nothing worked.我什至尝试了基本上所有的编码,甚至没有编码,但没有任何效果。

  • I tried writing to the BaseStream myself:我尝试自己写信给BaseStream
byte[] buffer = Encoding.ASCII.GetBytes("5");
CoutN.StandardInput.BaseStream.Write(buffer, 0, buffer.Length);
CoutN.StandardInput.WriteLine();

And that didn't work.那没有用。

At this point I feel like I've exhausted all the options that I could try.在这一点上,我觉得我已经用尽了所有可以尝试的选项。 Any help is appreciated, thanks in advance!任何帮助表示赞赏,在此先感谢!

You don't get to chose what encoding the other process is using from your own code - if you're sending input to the standard input stream of an application that is expecting a specific encoding, then short of it having some setting to change that there's nothing you can do about it.您无法从您自己的代码中选择其他进程使用的编码 - 如果您将输入发送到应用程序的标准输入 stream,该应用程序需要特定编码,那么它缺少一些设置来更改它你无能为力。

If you're interacting with the STDIO streams of another application, you are expected to match whatever encoding it is expecting, rather than the other way around.如果您正在与另一个应用程序的 STDIO 流进行交互,您应该匹配它所期望的任何编码,而不是相反。 The encoding of the console doesn't really matter except in cases where the application inherits its encoding from the environment.控制台的编码并不重要,除非应用程序从环境中继承其编码。

Indeed, if you're trying to use an encoding that supports Cyrillic characters, then the receiving application must have been designed to accommodate this.实际上,如果您尝试使用支持西里尔字符的编码,那么接收应用程序必须设计为适应这种情况。 If the application was written by someone whose native character set only uses Latin characters then they may well have never bothered to do this.如果应用程序是由其本地字符集仅使用拉丁字符的人编写的,那么他们很可能从未费心这样做。 It's part of the reason for the push to adopt UTF8 everywhere since then you don't really need to think about it too much.这是推动在任何地方采用 UTF8 的部分原因,因为从那时起你真的不需要考虑太多。

Edit: If you're trying to match the expected input encoding, then you do it thusly:编辑:如果您尝试匹配预期的输入编码,那么您可以这样做:

Process.StandardInput.Write(Encoding.ASCII.GetBytes("My String Here\r\n"));

Replacing Encoding.ASCII with whatever character set applies to get the appropriate GetBytes() method.用任何适用的字符集替换Encoding.ASCII以获得适当的GetBytes()方法。

Note that the ASCII character set specifically does not include Cyrillic characters, so it's impossible to use them in an application that expects ASCII.请注意,ASCII 字符集特别不包括西里尔字符,因此不可能在需要 ASCII 的应用程序中使用它们。 If it expects some other character set that does support them then you're fine.如果它需要一些其他支持它们的字符集,那么你很好。 Cyrillic uses Codepage 855 or needs UTF8. Cyrillic 使用 Codepage 855 或需要 UTF8。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM