我最终使用了LCMapStringEx
它,它对我来说很好用。它不是基于(任意集合)CompareOptions
,而是CompareInfo.GetSortKey 文档引导我LCMapString
,因此我indexOf
的规范化字符串的效果应该与CultureInfo.CompareInfo.IndexOf
使用硬编码产生相同的结果CompareOptions
,这里称为dwMapFlags
:
public static string Canonicalize(string src)
{
string localeName = "ja-JP";
string nResult = src;
int nLen, nSize;
uint dwMapFlags = LCMAP_LOWERCASE | LCMAP_HIRAGANA | LCMAP_FULLWIDTH;
IntPtr ptr, pZero = IntPtr.Zero;
nLen = src.Length;
nSize = LCMapStringEx(localeName, dwMapFlags, src, nLen, IntPtr.Zero, 0, pZero, pZero, pZero);
if (nSize > 0)
{
nSize = nSize * sizeof(char);
ptr = Marshal.AllocHGlobal(nSize);
try
{
nSize = LCMapStringEx(localeName, dwMapFlags, src, nLen, ptr, nSize, pZero, pZero, pZero);
if (nSize > 0) nResult = Marshal.PtrToStringUni(ptr, nSize);
}
finally
{
Marshal.FreeHGlobal(ptr);
}
}
return nResult;
}
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
static extern int LCMapStringEx(
string lpLocaleName,
uint dwMapFlags,
string lpSrcStr,
int cchSrc,
[Out]
IntPtr lpDestStr,
int cchDest,
IntPtr lpVersionInformation,
IntPtr lpReserved,
IntPtr sortHandle);
private const uint LCMAP_LOWERCASE = 0x100;
private const uint LCMAP_UPPERCASE = 0x200;
private const uint LCMAP_SORTKEY = 0x400;
private const uint LCMAP_BYTEREV = 0x800;
private const uint LCMAP_HIRAGANA = 0x100000;
private const uint LCMAP_KATAKANA = 0x200000;
private const uint LCMAP_HALFWIDTH = 0x400000;
private const uint LCMAP_FULLWIDTH = 0x800000;
我还尝试了Microsoft.VisualBasic.StrConv,它可以工作,但速度是 pinvoking 的两倍LCMapStringEx
。