【问题标题】:Is there a function in vb.net that will tell us whether 2 string is equivalent under UTF8 unicode collation?vb.net 中是否有一个函数可以告诉我们 2 个字符串在 UTF8 unicode 排序规则下是否等效?
【发布时间】:2012-05-29 14:37:38
【问题描述】:

这个问题类似于How to emulate MySQLs utf8_general_ci collation in PHP string comparisons,但我想要 vb.net 的函数而不是 PhP。

最近我做了很多据说是唯一的钥匙。

某些键在 UTF8 unicode 排序规则下是等效的。

例如,看看这 2 个关键:

拜尔斯街小酒馆__38.15_-79.07 拜尔斯街小酒馆‎__38.15_-79.07

如果我将它粘贴到首页,然后查看您会看到的源代码

byers-street-bistro__38.15_-79.07

byers-street-bistro‎__38.15_-79.07

注意:在堆栈溢出中它们看起来仍然不同。

我知道这不一样。我想即使在堆栈交换中它也不会显示。假设我有 100 万条这样的记录,我想测试 MySQL UTF8 排序规则是否将 2 个字符串声明为相同。我想在上传之前知道这一点。我该怎么做。

所以 vb.net 认为这些是不同的键。当我们创建 mysql 查询并将其上传到数据库时,数据库抱怨它是同一个键。一个投诉,100万个数据库的上传就卡住了。

我们甚至不知道到底是什么?我们在哪里可以查到呢?

无论如何,我想要一个函数,当给定 2 个字符串时,它会告诉我它们是否会被视为相同。

如果可能的话,我们想要一个将字符串转换成最“标准”形式的函数。

例如,‎似乎什么都不编码,该函数会重新识别所有这些无字符并消除它。

有这种事吗?

到目前为止,这就是我所做的。我需要更全面的东西。

    Private Function StraightenQuotesReplacement() As Generic.Dictionary(Of String, String)
    Static replacement As Generic.Dictionary(Of String, String)
    If replacement Is Nothing Then
        replacement = New Generic.Dictionary(Of String, String)
        replacement.Add(ChrW(&H201C), """")
        replacement.Add(ChrW(&H201D), """")
        replacement.Add(ChrW(&H2018), "'")
        replacement.Add(ChrW(&H2019), "'")
    End If
    Return replacement
End Function

<Extension()>
Public Function straightenQuotes(ByVal somestring As String) As String
    For Each key In StraightenQuotesReplacement.Keys
        somestring = somestring.Replace(key, StraightenQuotesReplacement.Item(key))
    Next
    Return somestring
End Function

<Extension()>
Public Function germanCharacter(ByVal s As String) As String
    Dim t = s
    t = t.Replace("ä", "ae")
    t = t.Replace("ö", "oe")
    t = t.Replace("ü", "ue")
    t = t.Replace("Ä", "Ae")
    t = t.Replace("Ö", "Oe")
    t = t.Replace("Ü", "Ue")
    t = t.Replace("ß", "ss")
    Return t
End Function
<Extension()>
Public Function japaneseCharacter(ByVal s As String) As String
    Dim t = s
    t = t.Replace("ヶ", "ケ")
    Return t
End Function

<Extension()>
Public Function greekCharacter(ByVal s As String) As String
    Dim t = s
    t = t.Replace("ς", "σ")
    t = t.Replace("ι", "ί")

    Return t
End Function
<Extension()>
Public Function franceCharacter(ByVal s As String) As String
    Dim t = s
    t = t.Replace("œ", "oe")
    Return t
End Function

<Extension()>
Public Function RemoveDiacritics(ByVal s As String) As String
    Dim normalizedString As String
    Dim stringBuilder As New StringBuilder
    normalizedString = s.Normalize(NormalizationForm.FormD)
    Dim i As Integer
    Dim c As Char
    For i = 0 To normalizedString.Length - 1
        c = normalizedString(i)
        If CharUnicodeInfo.GetUnicodeCategory(c) <> UnicodeCategory.NonSpacingMark Then
            stringBuilder.Append(c)
        End If
    Next
    Return stringBuilder.ToString()
End Function

<Extension()>
Public Function badcharacters(ByVal s As String) As String
    Dim t = s
    t = t.Replace(ChrW(8206), "")
    Return t
End Function

<Extension()>
Public Function sanitizeUTF8_Unicode(ByVal str As String) As String
    Return str.ToLower.removeDoubleSpaces.SpacetoDash.EncodeUrlLimited.straightenQuotes.RemoveDiacritics.greekCharacter.germanCharacter
End Function

【问题讨论】:

    标签: vb.net utf-8 collation


    【解决方案1】:

    可能对看起来相似的字符使用不同的 unicode 代码点,例如连字符减号 (- U+002D)、短划线 (- U+2013) 和长破折号 (- U+2014) 是三个看起来相似的不同字符:- - -

    使用 AscW() 函数检查每个字符。

    编辑:

    如下面的 cmets 所述,使用 System.Text.NormalizationForm 命名空间来确定哪些 Unicode 代码点被视为等效字符。

    【讨论】:

    • 我需要能够以编程方式执行此操作。无需人为干预说明“ä”与“ae”是一样的
    • 如果您在 System.Text.NormalizationForm 上搜索 Visual Studio 帮助,我想您可能会找到答案。让我们知道您的发现!
    • 这样就可以了。我想我需要更多。
    • 请将您的评论变成答案。
    • 这行得通,但并不完美。看stackoverflow.com/questions/11354999/…
    【解决方案2】:

    我使用下面的 VBA 代码来调查奇怪的字符串。

    我将“byers-street”行复制到 Excel 工作表的 D18 单元格,并在“即时”窗口中键入 call DsplInHex(Range("D18"))。结果是:

    62 79 65 72 73 2D 73 74 72 65 65 74 2D 62 69 73 74 72 6F 5F 33 38 2E 31 35 2D 37 39 2E 30 37 20 62 79 65 72 73 2D 73 74 72 65 65 74 2D 62 69 73 74 72 6F 200E 5F 33 38 2E 31 35 2D 37 39 2E 30 37 
    

    添加换行符和一些空格给出:

    62 79 65 72 73 2D 73 74 72 65 65 74 2D 62 69 73 74 72 6F      5F 33 38 2E 31 35 2D 37 39 2E 30 37 20 
    62 79 65 72 73 2D 73 74 72 65 65 74 2D 62 69 73 74 72 6F 200E 5F 33 38 2E 31 35 2D 37 39 2E 30 37 
    

    根据我的 Unicode 书 200ELeft-To-Right Mark。我很想知道您是如何设法将该字符添加到您的密钥中的。

    VB.NET 是正确的;这些键是不同的。 MySQL 删除了此类字符,或者您的传输过程将其删除。无论哪种方式,您都需要检查源数据中是否有有趣的字符。

    Option Explicit
    Public Sub DsplInHex(Stg As String)
    
      Dim Pos As Long
    
      For Pos = 1 To Len(Stg)
        Debug.Print Hex(AscW(Mid(Stg, Pos, 1))) & " ";
      Next
      Debug.Print
    
    End Sub
    

    【讨论】:

    • 我知道不一样。我想即使在堆栈交换中它也不会显示。假设我有 100 万条这样的记录,我想测试 2 个字符串是否会被 MySQL 声明为相同。我想在上传之前知道这一点。我该怎么做。
    • Left-To-Right Mark 是一个隐形字符;它不会显示在任何地方。你知道你是怎么把这个角色变成钥匙的吗?除了通过程序,我不知道如何插入这样的字符。了解可能有助于确定您需要检查哪些键。如果做不到这一点,我会检查每条记录(包括键)是否有 AscW 值大于 255 或可能为 127 的字符并删除它们。
    • 顺便说一句。您的示例没有显示等效问题。这与智能引号或连字符与破折号不同。这是一个我认为不应该出现的角色。我没有从右到左阅读的字母的经验。我假设这个字符和它的伙伴允许你混合从左到右和从右到左的字母。
    • 该字符被 utf-8 排序规则忽略。所以我认为 utf-8 排序规则必须将这些字符映射为空,然后比较字符串。我想要那些地图。
    • 也许我误解了“排序规则”,但我会解释我看到的问题。 "There's" 与 "There's" 不同,因为第一个包含一个智能引号 (201B),而第二个包含一个普通引号 (27)。智能或普通报价是一个整理问题。 “byers-street-bistro_38.15-79.07”与“byers-street-bistro‎_38.15-79.07”不同,因为第二个包含不可见字符 (200E) 而第一个不包含。额外的字符不是排序规则问题。 为什么要在第二个键中使用 LTM 字符?
    猜你喜欢
    • 1970-01-01
    • 2012-01-04
    • 1970-01-01
    • 1970-01-01
    • 2021-09-30
    • 2014-07-19
    • 2022-08-16
    • 2020-03-18
    • 2012-03-13
    相关资源
    最近更新 更多