C# 问题中的另一个 Encoding/Decoding

Another Encoding/Decoding in C# Issue

我一直在为 CLI 开发 GUI。我不是将所有内容都写入文本文件,而是重定向标准输出,然后使用我可以在 GUI 代码中 use/reuse 的输出创建一个 abject。我已经尝试了我遇到的所有可能的解决方案,但我还没有完全解决这个问题。几乎就像 return 中的每一行都以两种不同的方式编码。这是我的命令行界面:

class CmdToolInteraction
{

    private static string returnString = null;

    public string runcommandline(string argumentString)
    {
        UnicodeEncoding uni = new UnicodeEncoding();
        Process proc;
        proc = new Process();
        proc.StartInfo.FileName = "cmd.exe";
        proc.StartInfo.Arguments = argumentString;

        proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;

        proc.StartInfo.UseShellExecute = false;

        proc.StartInfo.RedirectStandardOutput = true;

        proc.StartInfo.RedirectStandardInput = true;

        proc.Start();

        StreamWriter cmdStreamWriter = proc.StandardInput;
        cmdStreamWriter.Write(argumentString);
        cmdStreamWriter.Close();

       returnString = uni.GetString(proc.StandardOutput.CurrentEncoding.GetBytes(proc.StandardOutput.ReadToEndAsync().Result));

        proc.WaitForExit();

        Console.Write(returnString);
        return returnString;

    }
}

我 运行 进入问题的地方显然是输出。其中一些是可读的英文白色,其余的是 jibberish/Chinese 即

"someone@somewhere.net਍  䰀愀渀最甀愀最攀㨀 攀渀ഀ\n Success਍ഀ"

在某些情况下,整行或 return 看起来像上面的后半部分,而我知道应该用英文字母数字代替。

哈尔普!

编辑:

我更新了上面的代码以添加 proc.Startinfo.StandardOutputEncoding = Encuding.Unicode

我仍然得到这个字符串 "someone@somewhere.net਍  䰀愀渀最甀愀最攀㨀 攀渀ഀ\n Success਍ഀ" 但我现在知道为什么了。在这种情况下,第二部分是 BigEndian unicode,而其余部分是 LittleEndian。现在我想弄清楚如何清理未解释的部分。

编辑 #2 在 roelands 的建议下,我采用了 unicode 输出并尝试将其转换为 ascii。类似的问题,但我觉得我越来越接近 "someone@somewhere.net਍  䰀愀渀最甀愀最攀㨀 攀渀ഀ\n Success਍ഀ" 现在读作 "someone@somewhere.net???????????????\n Success??"

我的解码设置为:

byte[] bytes = Encoding.ASCII.GetBytes(proc.StandardOutput.ReadToEnd());
returnString = Encoding.ASCII.GetString(bytes);

我认为这确实是一个编码问题。这是字节列表(字符串的一部分),假设该字符串是 UTF-16 little endian。仔细查看换行符周围的字节:

119 'w'
  0
104 'h'
  0
101 'e'
  0
114 'r'
  0
101 'e'
  0
 46 '.'
  0
110 'n'
  0
101 'e'
  0
116 't'
  0
 13 CR
 10 LF
  0
 32 ' '
  0
 32 ' '
  0
 76 'L'
  0
 97 'a'
  0
110 'n'
  0
103 'g'
  0
117 'u'
  0

在某些时候,UTF-16 字节流被解释为 ANSI 文本,换行符 ("\n") 被扩展为 CR-LF 对,从而破坏了 UTF-16 字符串。

解决方案取决于您的程序的工作方式。您需要通过 CMD 命令处理器 运行 程序吗?如果是这样,您是否使用 /U 选项?否则,你能以二进制模式打开 I/O 流吗?

您对字符串和编码的理解似乎有些混乱。 该行:

returnString = uni.GetString(proc.StandardOutput.CurrentEncoding.GetBytes(proc.StandardOutput.ReadToEndAsync().Result));

完全没有意义。 proc.StandardOutput.ReadToEndAsync().Result (^) 已经 returns 一个字符串。这意味着控制台输出中的字节流已经被编码成一个字符串。 .Net 中字符串的内部表示恰好是 UTF-16,但您不应该关心它是什么。 string 对象是 well 字符串的不透明表示。一旦你有了一个字符串,你就不应该关心它是如何在内部存储的。当您将它转换回字节时,您只需要关心它。然后您需要选择该字符串的表示方式(即要使用的编码)。

为了获得 cmd 进程的输出,您应该调用:

returnString = proc.StandardOutput.ReadToEnd();
p.WaitForExit();

如果您仍然遇到乱码,那么可以查看命令控制台内的应用程序 运行ning。我敢打赌,如果你 运行 在外部命令控制台中输入你的参数,你会得到相同的结果。

(^) 为什么使用 ReadToEndAsync().Result 而不是 ReadToEnd