c# - 由文化敏感的 String.IndexOf 方法匹配的子字符串的长度

标签 c# .net unicode substring

我尝试编写一个文化感知字符串替换方法:

public static string Replace(string text, string oldValue, string newValue)
{
    int index = text.IndexOf(oldValue, StringComparison.CurrentCulture);
    return index >= 0
        ? text.Substring(0, index) + newValue + text.Substring(index + oldValue.Length)
        : text;
}

但是,它会在 Unicode 组合字符时阻塞:

// \u0301 is Combining Acute Accent
Console.WriteLine(Replace("déf", "é", "o"));       // 1. CORRECT: dof
Console.WriteLine(Replace("déf", "e\u0301", "o")); // 2. INCORRECT: do
Console.WriteLine(Replace("de\u0301f", "é", "o")); // 3. INCORRECT: dóf

要修复我的代码,我需要知道在第二个示例中,String.IndexOf 仅匹配一个字符 (é),即使它搜索了两个 (e\u0301)。同样,我需要知道在第三个示例中,String.IndexOf 匹配了两个字符 (e\u0301),即使它只搜索了一个 (é)。

如何确定String.IndexOf匹配的子串的实际长度?

注意:对 textoldValue 执行 Unicode 规范化(如 James Keesey 所建议的那样)将适应组合字符,但连字仍然是一个问题:

Console.WriteLine(Replace("œf", "œ", "i"));  // 4. CORRECT: if
Console.WriteLine(Replace("œf", "oe", "i")); // 5. INCORRECT: i
Console.WriteLine(Replace("oef", "œ", "i")); // 6. INCORRECT: ief

最佳答案

您需要直接调用 FindNLSStringFindNLSStringEx你自己。 String.IndexOf 使用 FindNLSStringEx但您需要的所有信息都可以在 FindNLSString 中找到.

这是一个示例,说明如何重写适用于测试用例的 Replace 方法。请注意,如果您想使用系统区域设置或提供您自己的区域设置,我使用的是当前用户区域设置,请阅读 API 文档。我还为标志传递了 0,这意味着它将使用区域设置的默认字符串比较选项,同样,文档可以帮助您提供不同的选项。

public const int LOCALE_USER_DEFAULT = 0x0400;

[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
internal static extern int FindNLSString(int locale, uint flags, [MarshalAs(UnmanagedType.LPWStr)] string sourceString, int sourceCount, [MarshalAs(UnmanagedType.LPWStr)] string findString, int findCount, out int found);

public static string ReplaceWithCombiningCharSupport(string text, string oldValue, string newValue)
{
    int foundLength;
    int index = FindNLSString(LOCALE_USER_DEFAULT, 0, text, text.Length, oldValue, oldValue.Length, out foundLength);
    return index >= 0 ? text.Substring(0, index) + newValue + text.Substring(index + foundLength) : text;
}

关于c# - 由文化敏感的 String.IndexOf 方法匹配的子字符串的长度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20480016/

相关文章:

c# - 如何使用 Linq-to-entities 检索分层数据?

c# - 创建 View 中可用的自定义助手

string - 为 unicode 字母写一个 toUpper 函数

php - 2 个 PHP 系统上的正则表达式输出不同?

python - 如何在 Python 3 中使用 unicode 字符作为变量?

c# - MVC 自动生成索引方法 - 为什么需要 .include?

c# - 自动封装字段重构, 'Use field' 和 'Use Property' 之间的区别?

.net - 使用 String.Format 进行数字格式化

c# - 如果我的配置文件缺少 log4net 配置部分,为什么我的应用程序会挂起?

c# - 从命令行传递参数时 Devenv 崩溃