【问题标题】:Convert Unicode char to closest (most similar) char in ASCII (.NET)将 Unicode 字符转换为 ASCII (.NET) 中最接近(最相似)的字符
【发布时间】:2011-02-07 03:41:42
【问题描述】:

如何将不同的 Unicode 字符转换为最接近的 ASCII 字符?就像 Ä -> A。我用谷歌搜索但没有找到任何合适的解决方案。技巧Encoding.ASCII.GetBytes("Ä")[0] 没有奏效。 (结果是?)。

我发现有一个类 Encoder 有一个 Fallback 属性,该属性恰好适用于 char 无法转换但实现 (EncoderReplacementFallback) 很愚蠢并转换为 ? 的情况.

有什么想法吗?

【问题讨论】:

  • 你如何定义“最接近的 ascii 等价物”?只是删除重音符号?
  • 好吧...如果除了转换为之外还有任何定义吗?我想要它:) 我认为在重音的情况下它只是删除。
  • @mmr:我不知道 Andrey 的预期用途,但我有一个程序应该接受文本并将其提供给稍后将显示它的附加设备。许多类型的附加设备买不起存储多字节字符所需的 RAM,无论如何也买不起存储超过 256 个字符字形所需的 ROM [大多数字符矩阵 LCD 模块具有固定的 160 个字符设置加上同时显示八个自定义 5x7 或 5x8 字形的能力]。将所有非 ASCII 文本呈现为“?”会显得不必要的丑陋。
  • @supercat 我的原因是我们正在发送国际短信,我们无法确定短信编码中是否存在符号(我不记得细节),所以我们同意它更好完全去掉变音符号而不是显示问号。但同样,我不记得细节。但本质上它与您的情况非常相似。

标签: .net unicode encoding ascii


【解决方案1】:

MS Dynamics 存在一个问题,它不允许 x20 到 x7f 之外的任何字符,并且该范围内的某些字符也是无效的。我的答案是创建一个以无效字符为键的数组,返回对有效字符的最佳猜测。
它不漂亮,但它有效。

Function PlainAscii(InText)
Dim i, c, a
Const cUTF7 = "^[\x20-\x7e]+$"
Const IgnoreCase = False
    PlainAscii = ""
    If InText = "" Then Exit Function
    If RegExTest(InText, cUTF7, IgnoreCase) Then
        PlainAscii = InText
    Else
        For i = 1 To Len(InText)
            c = Mid(InText, i, 1)
            a = Asc(c)
            If a = 10 Or a = 13 Or a = 9 Then
                ' Do Nothing - Allow LF, CR & TAB
            ElseIf a < 32 Then
                c = " "
            ElseIf a > 126 Then
                c = CvtToAscii(a)
            End If
            PlainAscii = PlainAscii & c
        Next
    End If
End Function

Function CvtToAscii(inChar)
' Maps The Characters With The 8th Bit Set To 7 Bit Characters
Dim arrChars
    arrChars = Array(" ", " ", "$", " ", ",", "f", """", " ", "t", "t", "^", "%", "S", "<", "O", " ", "Z", " ", " ", "'", "'", """", """", ".", "-", "-", "~", "T", "S", ">", "o", " ", "Z", "Y", " ", "!", "$", "$", "o", "$", "|", "S", " ", "c", " ", " ", " ", "_", "R", "_", ".", " ", " ", " ", " ", "u", "P", ".", ",", "i", " ", " ", " ", " ", " ", " ", "A", "A", "A", "A", "A", "A", "A", "C", "E", "E", "E", "E", "I", "I", "I", "I", "D", "N", "O", "O", "O", "O", "O", "X", "O", "U", "U", "U", "U", "Y", "b", "B", "a", "a", "a", "a", "a", "a", "a", "c", "e", "e", "e", "e", "i", "i", "i", "i", "o", "n", "o", "o", "o", "o", "o", "/", "O", "u", "u", "u", "u", "y", "p", "y")
    CvtToAscii = arrChars(inChar - 127)
End Function

Function RegExTest(ByVal strStringToSearch, strExpression, IgnoreCase)
Dim objRegEx
    On Error Resume Next
    Err.Clear
    strStringToSearch = Replace(Replace(strStringToSearch, vbCr, ""), vbLf, "")
    RegExTest = False
    Set objRegEx = New RegExp
    With objRegEx
        .Pattern = strExpression    '//the reg expression that should be searched for
        If Err.Number = 0 Then
            .IgnoreCase = CBool(IgnoreCase)    '//not case sensitive
            .Global = True              '//match all instances of pattern
            RegExTest = .Test(strStringToSearch)
        End If
    End With
    Set objRegEx = Nothing
    On Error Goto 0
End Function

你的答案必然会有所不同。

【讨论】:

    【解决方案2】:

    如果只是删除diacritical marks,则前往this answer

    static string RemoveDiacritics(string stIn) {
      string stFormD = stIn.Normalize(NormalizationForm.FormD);
      StringBuilder sb = new StringBuilder();
    
      for(int ich = 0; ich < stFormD.Length; ich++) {
        UnicodeCategory uc = CharUnicodeInfo.GetUnicodeCategory(stFormD[ich]);
        if(uc != UnicodeCategory.NonSpacingMark) {
          sb.Append(stFormD[ich]);
        }
      }
    
      return(sb.ToString().Normalize(NormalizationForm.FormC));
    }
    

    【讨论】:

      猜你喜欢
      • 2018-11-19
      • 2018-11-18
      • 2012-08-02
      • 2018-03-21
      • 2013-01-26
      • 1970-01-01
      • 1970-01-01
      • 2012-05-27
      相关资源
      最近更新 更多