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
?
我一直在为 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
?