我需要帮助将C#字符串从一个字符编码转换为另一个字符编码?

时间:2011-02-25 06:26:49

标签: c# character-encoding ftps

根据Spolsky我不能称自己为开发者,所以这个问题背后有很多耻辱......

场景:从C#应用程序中,我想从SQL db中获取一个字符串值,并将其用作目录的名称。我有一个安全(SSL)FTP服务器,我想在其上使用数据库中的字符串值设置当前目录 问题:一切正常,直到我点击一个带有“特殊”字符的字符串值 - 我似乎无法正确编码目录名以满足FTP服务器。

下面的代码示例

  • 使用“特殊”字符é作为示例
  • 使用WinSCP作为ftps通信的外部应用程序
  • 未显示设置Process“_winscp”所需的所有代码。
  • 通过写入进程standardinput
  • 将命令发送到WinSCP exe
  • 为简单起见,没有从DB获取信息,而是简单地声明一个字符串(但我确实做了一个.Equals来确认DB中的值与声明的字符串相同)
  • 尝试使用不同的字符串编码在FTP服务器上设置当前目录三次 - 所有这些都失败
  • 尝试使用从手工制作的字节数组创建的字符串设置目录 - 这可以正常工作

Process _winscp = new Process();
byte[] buffer;

string nameFromString = "Sinéad O'Connor";
_winscp.StandardInput.WriteLine("cd \"" + nameFromString + "\"");

buffer = Encoding.UTF8.GetBytes(nameFromString);
_winscp.StandardInput.WriteLine("cd \"" + Encoding.UTF8.GetString(buffer) + "\"");

buffer = Encoding.ASCII.GetBytes(nameFromString);
_winscp.StandardInput.WriteLine("cd \"" + Encoding.ASCII.GetString(buffer) + "\"");

byte[] nameFromBytes = new byte[] { 83, 105, 110, 130, 97, 100, 32, 79, 39, 67, 111, 110, 110, 111, 114 };
_winscp.StandardInput.WriteLine("cd \"" + Encoding.Default.GetString(nameFromBytes) + "\"");

UTF8编码将é更改为101(十进制),但FTP服务器不喜欢它。

ASCII编码将é更改为63(十进制),但FTP服务器不喜欢它。

当我将é表示为值130(十进制)时,FTP服务器很高兴,除了我找不到一个能为我做这个的方法(我不得不从显式字节手动构造字符串)。

任何人都知道我应该对我的字符串做什么来将é编码为130并使FTP服务器满意并最终通过解释开发人员 应该理解的唯一一件事来提升我为1级开发人员?

2 个答案:

答案 0 :(得分:4)

130不是ASCII(ASCII只有7位 - 参见Encoding.ASCII文档 - 所以它将“é”打成正常的“?”,因为它没有更好的事情要做)。 UTF-8实际上将字符编码为两个字节(十进制:195和169),但保留了代码点。

明确使用代码页,例如Latin (CP 1252) - 需要匹配其他任何方面。从下面开始,输出中没有“130”,所以...不是您需要的编码:-)但同样适用:对特定代码页使用编码。

修改:正如Hans Passant在评论中解释的那样,此处使用的代码页为MS-DOS (CP 437),这将产生所需的结果。

// LINQPad -- Encoding is System.Text.Encoding
var enc = Encoding.GetEncoding(1252);
string.Join(" ", enc.GetBytes("Sinéad O'Connor")).Dump();
// -> 83 105 110 233 97 100 32 79 39 67 111 110 110 111 114

请参阅:http://msdn.microsoft.com/en-us/goglobal/bb688114了解更多信息。

快乐的编码。

顺便说一下。艺术家的精选 - 如果是故意的话:p

答案 1 :(得分:1)

我认为这里的问题是所有.NET字符串都是Unicode。 .NET字符串中没有“我是什么编码”。因此,使用Encoding.ASCII.GetString(buffer)将ASCII中的“字符串”转换回Unicode。

我认为您的问题应该通过更改Process.StandardInput的编码来解决,因此您可以在WinSCP中获得正确的编码。

您应该检查Encoding.Default是什么,因为我很确定它不是UTF8或ASCII。