1

我需要的是类似于每个ASCII字符的等效Unicode字符列表。有没有办法将文本从Unicode转换为ASCII?

问题在于,当人们输入文档时,Microsoft Excel和Word等程序会插入非ASCII双引号,单引号,短划线等。我想将此文本存储在类型为“varchar”的数据库字段中,该字段需要单字节字符。

为了存储ASCII(单字节)文本,这些Unicode字符中的一些可以被认为等同于或类似于特定的ASCII字符,用等同的ASCII字符替换Unicode字符将会很好。

我想要一个像MapToASCII这样简单的函数,它可以将Unicode文本转换为ASCII等效文本,从而允许为任何与任何ASCII字符都不相似的Unicode字符指定替换字符。

+0

另请参阅http:// stackoverflow。com/questions/138449/how-to-convert-a-unicode-character-to-its-ascii-equivalent – 2011-04-13 20:23:07

+0

该链接与我的问题无关,以及所有评论与我发布的链接相关的地方在哪里?这个问题看起来很相似,但它确实在问如何编码一个特定的代码页(因此GetEncoding.GetBytes),而不是将Unicode Unicode字符转换为等效的ASCII字符,这完全与编码无关。我感兴趣的是像WordPress的函数remove_accents(http://stackoverflow.com/questions/138449/how-to-convert-a-unicode-character-to-its-ascii-equivalent/1748412#1748412)可怜的人下了船 - IMO投票给了一个好的答案,虽然有点缺陷。 – Triynko 2011-04-13 21:06:31

+1

现在这是高度相关性>> http://stackoverflow.com/questions/4808967/replacing-unicode-punctuation-with-ascii-approximations – Triynko 2011-04-14 16:48:32

回答

1

Win32 API WideCharToMultiByte可用于此转换(从Unicode到ANSI)。使用CP_ACP作为第一个参数。像这样的东西可能会比尝试构建自己的映射函数更好。

编辑在听起来像我想推动这个作为对OP的意愿的解决方案的风险,似乎它可能是值得指出的是,这个API做很多(所有?),现在被要求对于。目标是尽可能将Unicode字符串映射(我认为)为“ANSI”(在这种情况下,ANSI可能是一个移动目标)。另一个要求是能够为那些不能映射的字符指定一些替代字符。以下示例执行此操作。它将一个Unicode字符串“转换”为char,并为那些无法转换的字符使用下划线(倒数第二个参数)。

ret = WideCharToMultiByte(CP_ACP, 0, L"abc個חあЖdef", -1, 
          ac, sizeof(ac), "_", NULL); 
for (i = 0; i < strlen(ac); i++) 
    printf("%c %02x\n", ac[i], ac[i]); 
+1

看起来像一个有趣的方式来拍摄自己的脚:“'CP_ACP': 系统默认的Windows ANSI代码页 注意:在不同的计算机上,即使在同一个网络上,该值也可能不同,可以在同一台计算机上更改,导致存储的数据无法恢复损坏。如果可能的话,使用和永久存储应该使用UTF-16或UTF-8。“但是,好像OP看起来像是互不相容的字符集的痛苦,而你的回答正确地让他这么做,所以+1。 – Piskvor 2011-04-13 15:09:08

+1

定义ANSI.诀窍 – tchrist 2011-04-13 15:11:57

+0

@Piskvor:的确如此!使用这个功能的结果只有大约5%的时间令人满意(而令人满意的是一个相对的术语;)但是,在不了解OP的要求的情况下,很难说;它可能实际上工作正常。 – 2011-04-13 15:25:16

0

高度相关的问题是在这里:Replacing unicode punctuation with ASCII approximations

虽然回答有不足,它给了我一个想法。我可以将基本多语言平面(0)中的每个Unicode代码点映射到等效的ASCII字符(如果存在)。以下C#代码将帮助您创建一个HTML表单,您可以在其中键入每个值的替换字符。

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Globalization; 
using System.IO; 

namespace UnicodeCharacterCategorizer 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      string output_filename = "output.htm"; //set a filename if not specifying one through the command line 
      Dictionary<UnicodeCategory,List<char>> category_character_sets = new Dictionary<UnicodeCategory,List<char>>(); 
      foreach (UnicodeCategory c in Enum.GetValues(typeof(UnicodeCategory))) 
       category_character_sets.Add(c, new List<char>()); 
      for (int i = 0; i <= 0xFFFF; i++) 
      { 
       if (i >= 0xD800 && i <= 0xDFFF) continue; //Skip ranges reserved for high/low surrogate pairs. 
       char c = (char)i; 
       UnicodeCategory category = char.GetUnicodeCategory(c); 
       category_character_sets[category].Add(c); 
      } 
      StringBuilder file_data = new StringBuilder(@"<!DOCTYPE html PUBLIC ""-//W3C//DTD XHTML 1.0 Transitional//EN"" ""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd""><html xmlns=""http://www.w3.org/1999/xhtml""><head><title>Unicode Category Character Sets</title><style>.categoryblock{border:3px solid black;margin-bottom:10px;padding:5px;} .characterblock{display:inline-block;border:1px solid grey;padding:5px;margin-right:5px;} .character{display:inline-block;font-weight:bold;background-color:#ffeeee} .numericvalue{color:blue;}</style></head><body><form id=""charactermap"">"); 
      foreach (KeyValuePair<UnicodeCategory,List<char>> entry in category_character_sets) 
      { 
       file_data.Append(@"<div class=""categoryblock""><h1>" + entry.Key.ToString() + ":</h1><br />"); 
       foreach (char c in entry.Value) 
       { 
        string hex_value = ((int)c).ToString("x"); 
        file_data.Append(@"<div class=""characterblock""><span class=""character"">&#x" + hex_value + @";<br /><span class=""numericvalue"">" + hex_value + @"</span><br /><input type=""text"" name=""r_" + hex_value + @""" /></div>"); 
       } 
       file_data.Append("</div>"); 
      } 
      file_data.Append("</form></body></html>"); 
      File.WriteAllText(output_filename, file_data.ToString(), Encoding.Unicode); 
     } 
    } 
} 

具体而言,代码将产生含有在BMP中的所有字符,与“R_”(R为“替换值”)为前缀的十六进制值命名的输入文本框沿着一个HTML表格。如果移植到ASP.NET页面,额外的代码可以被写入到预填充替代值尽可能:如果已经ASCII

  • 自己的价值,或者
  • 使用Unicode标准化FormD或FormKD分解等价物,或
  • 为一整类单个ASCII值(即所有的“标点初始”与ASCII双引号字符)

然后你可以去通过手动做出调整,它可能止跌只要你想,就花不了多久。只有64512个代码点,并且整个类别的大块可能被解雇为“甚至不接近任何ASCII”。所以,我要建立这个地图和功能。

+0

我刚刚发现了Encoding类的DecoderFallback属性:请参阅http://msdn.microsoft。 com/en-us/library/system.text.decoderfallback.aspx“最佳拟合后备,将无法解码的有效Unicode字符映射到近似等效。例如,ASCIIEncoding类的最适合后备处理程序可能会将Æ(U + 00C6)映射到AE(U + 0041 + U + 0045)。一个最适合的后备处理程序也可以用于将一个字母(例如西里尔字母)音译为另一个(例如拉丁或罗马)。 ** .NET框架没有提供任何公共的最佳适用的后备实现**“ – Triynko 2011-04-14 20:16:40

+0

这是对我正在尝试做的事情的一个NICE描述。是的,它表示尝试映射Unicode到一个坏主意ASCII,但如果你打算这样做,这篇文章可以帮助你思考你在做什么 - http://blogs.msdn.com/b/shawnste/archive/2006/01/19/515047.aspx – Triynko 2011-04-14 20:19:46

+0

有关实施编码后退策略的信息可以在这里找到 - http://msdn.microsoft.com/en-us/library/ms404377(v=VS.100).aspx你只需要实现你自己的DecoderFallback版本和DecoderFallbackBuffer。 – Triynko 2011-04-14 21:06:56

相关问题