对于每个ASCII字符,我需要的是类似的Unicode字符列表。
问题是当人们输入文档时,像Microsoft Excel和Word这样的程序会插入非ASCII双引号,单引号,破折号等。我想将此文本存储在“varchar”类型的数据库字段中,该字段需要单字节字符。
为了存储ASCII(单字节)文本,可以认为其中一些Unicode字符与特定的ASCII字符相当或相似,用等效的ASCII字符替换Unicode字符就可以了。
我想要一个像MapToASCII这样的简单函数,它可以将Unicode文本转换为ASCII等价物,允许我为任何与任何ASCII字符都不相似的Unicode字符指定替换字符。
答案 0 :(得分: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 :(得分:0)
这里有一个高度相关的问题:Replacing unicode punctuation with ASCII approximations
虽然答案不够,但它给了我一个想法。我可以将Basic Multilingual Plane(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 );
}
}
}
具体来说,该代码将生成一个HTML表单,其中包含BMP中的所有字符,以及以前缀为“r_”的十六进制值命名的输入文本框(r表示“替换值”)。如果将其移植到ASP.NET页面,则可以编写其他代码以尽可能地预先填充替换值:
然后,您可以手动完成并进行调整,这可能不会像您想象的那样长。只有64512个代码点,整个类别的大块可能被解雇为“甚至不接近任何ASCII”。所以,我要构建这个地图和功能。