【发布时间】:2012-05-07 15:32:14
【问题描述】:
我有一个在两个应用程序之间共享的 sql-server 2010 数据库。我们可以控制一个应用程序,而另一个应用程序是最初创建数据库的第三方应用程序。我们的应用程序是建立在第三方网络邮件应用程序之上的 CRM。
数据库包含 varchar 列并且是 latin-1 编码的。第三方应用程序是用 php 编写的,并不关心数据的正确编码,因此它将 utf-8 编码字节填充到 varchar 列中,在那里它们被解释为 latin-1 并且看起来像垃圾。
我们的 CRM 应用程序是用 .Net 编写的,它会自动检测数据库排序规则与内存中字符串的编码不同,因此当 .Net 写入数据库时,它会转换字节以匹配数据库编码。
所以...从我们的应用程序写入数据库的数据在数据库中看起来是正确的,但来自第三方应用程序的数据却不是。
当我们的应用写入 FirstName = Céline 时,它作为 Céline 存储在数据库中
当网络邮件应用程序写入 FirstName = Céline 时,它作为 Céline 存储在数据库中
我们的 CRM 应用需要显示在任一系统中创建的联系人。因此,我正在编写一个 EncodingSniffer 类,该类会查找指示其编码不佳的字符串的标记字符并进行转换。
目前我有:
私有静态字符串 [] _flaggedChars = 新字符串 [] { “©” };这非常适合将 Céline 显示为 Céline,但我需要添加到列表中。
有没有人知道一个资源来获取 utf-8 特殊字符可以被解释为 iso-8859-1 的所有可能方式?
谢谢
澄清: 因为我在.Net 工作。当从数据库加载到内存中时,该字符串将转换为 Unicode UTF-16。因此,无论它是否在数据库中正确编码。它现在表示为 UTF16 字节。我需要能够分析这些 UTF-16 字节,并确定它们是否由于 utf-8 字节被填充到 iso-8859-1 数据库中而搞砸了....像泥巴一样清楚吗?
这是我到目前为止所拥有的。它已经清除了大多数错误编码字符的显示,但我仍然无法使用 É 例如:Éric 通过 webmail 以 Éric 存储在数据库中,但在检测到错误编码并将其改回后,它显示为 ?ric 看看有 2500 个联系人的用户,其中数百个有编码问题,É 是唯一不能正确显示的东西......
public static Regex CreateRegex()
{
string specials = "ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö";
List<string> flags = new List<string>();
foreach (char c in specials)
{
string interpretedAsLatin1 = Encoding.GetEncoding("iso-8859-1").GetString(Encoding.UTF8.GetBytes(c.ToString())).Trim();//take the specials, treat them as utf-8, interpret them as latin-1
if (interpretedAsLatin1.Length > 0)//utf-8 chars made up of 2 bytes, interpreted as two single byte latin-1 chars.
flags.Add(interpretedAsLatin1);
}
string regex = string.Empty;
foreach (string s in flags)
{
if (regex.Length > 0)
regex += '|';
regex += s;
}
return new Regex("(" + regex + ")");
}
public static string CheckUTF(string data)
{
Match match = CreateRegex().Match(data);
if (match.Success)
return Encoding.UTF8.GetString(Encoding.GetEncoding("iso-8859-1").GetBytes(data));//from iso-8859-1 (latin-1) to utf-8
else
return data;
}
所以:É 被转换为 195'Ã',8240'‰'
【问题讨论】:
-
是否可以将 DB 编码更改为 UTF-8,这似乎是最简单的解决方案,因为 unicode 和 latin-1 之间没有一对一的转换
-
测试字符串是否有效 UTF-8 可能是更好的方法。 (可能也更便宜。)
-
@Mat,这基本上就是我想要做的,我只是不知道怎么做。坏字符嗅探方法是我想出的最好的方法。您将如何测试有效的 utf-8?
-
@Evan,不,不是 sqlserver 2010 中的选项。我们确实尝试将列的数据类型切换为 nvarchar .. 但应用程序创建 sql 查询字符串而不是使用存储过程。所以我们认为它可能会说:set column = 'somestring',而不是:set column = N'somestring',所以即使使用 nvarchar 列,它仍然在填充 varchar 数据...
-
@Michael Éric 中的 É 通过使用编码“Windows-1252”(西欧)或“windows-1254”(土耳其语)而不是 CheckUTF 中的“iso-8859-1”来修复( )。不需要 Unicode 去/重新规范化。 (我敢肯定它一直困扰着你)谢谢你的代码!
标签: encoding utf-8 iso-8859-1