非常に有益な回答をありがとうございました。実際の質問は「Unicode文字をASCIIフォールバックに変換するにはどうすればよいですか」ではなく、「顧客が不満を言っているUnicode文字をASCIIフォールバックに変換するにはどうすればよいですか」ということです。
言い換えれば、汎用ソリューションは必要ありません。英語を話す顧客がWordや他のWebサイトからアプリケーションに英語のコンテンツを貼り付けるために、99%の時間で機能するソリューションが必要です。そのために、次のテストを使用して、システムを介して送信された8年分のメッセージを分析し、ASCIIエンコードで表現できない文字を探しました。
///<summary>Determine whether the supplied character is
///using ASCII encoding.</summary>
bool IsAscii(char inputChar) {
var ascii = new ASCIIEncoding();
var asciiChar = (char)(ascii.GetBytes(inputChar.ToString())[0]);
return(asciiChar == inputChar);
}
次に、結果として得られた表現できない文字のセットを調べ、適切な置換文字列を手動で割り当てました。ロット全体が拡張メソッドにバンドルされているため、myString.Asciify()を呼び出して、文字列を適切なASCIIエンコード近似に変換できます。
public static class StringExtensions {
private static readonly Dictionary<char, string> Replacements = new Dictionary<char, string>();
/// <summary>Returns the specified string with characters not representable in ASCII codepage 437 converted to a suitable representative equivalent. Yes, this is lossy.</summary>
/// <param name="s">A string.</param>
/// <returns>The supplied string, with smart quotes, fractions, accents and punctuation marks 'normalized' to ASCII equivalents.</returns>
/// <remarks>This method is lossy. It's a bit of a hack that we use to get clean ASCII text for sending to downlevel e-mail clients.</remarks>
public static string Asciify(this string s) {
return (String.Join(String.Empty, s.Select(c => Asciify(c)).ToArray()));
}
private static string Asciify(char x) {
return Replacements.ContainsKey(x) ? (Replacements[x]) : (x.ToString());
}
static StringExtensions() {
Replacements['’'] = "'"; // 75151 occurrences
Replacements['–'] = "-"; // 23018 occurrences
Replacements['‘'] = "'"; // 9783 occurrences
Replacements['”'] = "\""; // 6938 occurrences
Replacements['“'] = "\""; // 6165 occurrences
Replacements['…'] = "..."; // 5547 occurrences
Replacements['£'] = "GBP"; // 3993 occurrences
Replacements['•'] = "*"; // 2371 occurrences
Replacements[' '] = " "; // 1529 occurrences
Replacements['é'] = "e"; // 878 occurrences
Replacements['ï'] = "i"; // 328 occurrences
Replacements['´'] = "'"; // 226 occurrences
Replacements['—'] = "-"; // 133 occurrences
Replacements['·'] = "*"; // 132 occurrences
Replacements['„'] = "\""; // 102 occurrences
Replacements['€'] = "EUR"; // 95 occurrences
Replacements['®'] = "(R)"; // 91 occurrences
Replacements['¹'] = "(1)"; // 80 occurrences
Replacements['«'] = "\""; // 79 occurrences
Replacements['è'] = "e"; // 79 occurrences
Replacements['á'] = "a"; // 55 occurrences
Replacements['™'] = "TM"; // 54 occurrences
Replacements['»'] = "\""; // 52 occurrences
Replacements['ç'] = "c"; // 52 occurrences
Replacements['½'] = "1/2"; // 48 occurrences
Replacements[''] = "-"; // 39 occurrences
Replacements['°'] = " degrees "; // 33 occurrences
Replacements['ä'] = "a"; // 33 occurrences
Replacements['É'] = "E"; // 31 occurrences
Replacements['‚'] = ","; // 31 occurrences
Replacements['ü'] = "u"; // 30 occurrences
Replacements['í'] = "i"; // 28 occurrences
Replacements['ë'] = "e"; // 26 occurrences
Replacements['ö'] = "o"; // 19 occurrences
Replacements['à'] = "a"; // 19 occurrences
Replacements['¬'] = " "; // 17 occurrences
Replacements['ó'] = "o"; // 15 occurrences
Replacements['â'] = "a"; // 13 occurrences
Replacements['ñ'] = "n"; // 13 occurrences
Replacements['ô'] = "o"; // 10 occurrences
Replacements['¨'] = ""; // 10 occurrences
Replacements['å'] = "a"; // 8 occurrences
Replacements['ã'] = "a"; // 8 occurrences
Replacements['ˆ'] = ""; // 8 occurrences
Replacements['©'] = "(c)"; // 6 occurrences
Replacements['Ä'] = "A"; // 6 occurrences
Replacements['Ï'] = "I"; // 5 occurrences
Replacements['ò'] = "o"; // 5 occurrences
Replacements['ê'] = "e"; // 5 occurrences
Replacements['î'] = "i"; // 5 occurrences
Replacements['Ü'] = "U"; // 5 occurrences
Replacements['Á'] = "A"; // 5 occurrences
Replacements['ß'] = "ss"; // 4 occurrences
Replacements['¾'] = "3/4"; // 4 occurrences
Replacements['È'] = "E"; // 4 occurrences
Replacements['¼'] = "1/4"; // 3 occurrences
Replacements['†'] = "+"; // 3 occurrences
Replacements['³'] = "'"; // 3 occurrences
Replacements['²'] = "'"; // 3 occurrences
Replacements['Ø'] = "O"; // 2 occurrences
Replacements['¸'] = ","; // 2 occurrences
Replacements['Ë'] = "E"; // 2 occurrences
Replacements['ú'] = "u"; // 2 occurrences
Replacements['Ö'] = "O"; // 2 occurrences
Replacements['û'] = "u"; // 2 occurrences
Replacements['Ú'] = "U"; // 2 occurrences
Replacements['Œ'] = "Oe"; // 2 occurrences
Replacements['º'] = "?"; // 1 occurrences
Replacements['‰'] = "0/00"; // 1 occurrences
Replacements['Å'] = "A"; // 1 occurrences
Replacements['ø'] = "o"; // 1 occurrences
Replacements['˜'] = "~"; // 1 occurrences
Replacements['æ'] = "ae"; // 1 occurrences
Replacements['ù'] = "u"; // 1 occurrences
Replacements['‹'] = "<"; // 1 occurrences
Replacements['±'] = "+/-"; // 1 occurrences
}
}
そこにはかなり奇妙なフォールバックがあることに注意してください-このように:
Replacements['³'] = "'"; // 3 occurrences
Replacements['²'] = "'"; // 3 occurrences
これは、ユーザーの1人がオープン/クローズのスマートクォートを²と³に変換するプログラムを持っていて(たとえば、彼は²hello³と言った)、べき乗を表すためにそれらを使用したことがないためです。 。