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

相關問題