将单字节字符串(半角)转换为双字节(全角)

Convert single byte character string (half width) to double byte (full width)

最近我在 C# 应用程序中看到这段代码。

cDataString = Strings.StrConv(cDataString, VbStrConv.Wide);

我了解到 StrConv 是 VB 的字符串函数。您可以通过包含 'using Microsoft.VisualBasic;'.

来调用它

应该将半角日文字符转换为全角字符。

我的问题是: 有没有一种方法可以在不使用 VB 函数并且不包含 VB headers 的情况下仅使用标准的 c# 函数来实现相同的目的?我知道有很多 c# 字符串转换函数,其中一些可以从 unicode 转换为 ansi,反之亦然等等。但我不确定其中任何一个是否会直接获得与上述 VB 完全相同的结果。那么,这可以在 c# 中完成吗?

感谢您的时间和努力。

更新: 我遇到了 5 年前被问到的 this question。答案和讨论确实显示了一些可以完成的方法。我特别想知道的是,在 5 年和新版本之后,有没有更简单更好的方法在 .NET 中执行此操作而不依赖于 VB 函数或 VB 库?

C# 中没有等效函数。

如果您遵循 Microsoft.VisualBasic.dllStrConv 的源代码,您会发现它实际上 p/invokes LCMapString 内部类似于 answer you linked .

如果你不想引用 Microsoft.VisualBasic.dll,你可以将 p/invoke 包装成一个帮助程序 class 或用 C# 编写的服务,像这样...

// NOTE: CODE NOT TESTED
// Code from John Estropia's Whosebug answer
// 

public static class StringWidthHelper
{
    private const uint LOCALE_SYSTEM_DEFAULT = 0x0800;
    private const uint LCMAP_HALFWIDTH = 0x00400000;
    private const uint LCMAP_FULLWIDTH = 0x00800000;

    public static string ToHalfWidth(string fullWidth)
    {
        StringBuilder sb = new StringBuilder(256);
        LCMapString(LOCALE_SYSTEM_DEFAULT, LCMAP_HALFWIDTH, fullWidth, -1, sb, sb.Capacity);
        return sb.ToString();
    }

    public static string ToFullWidth(string halfWidth)
    {
        StringBuilder sb = new StringBuilder(256);
        LCMapString(LOCALE_SYSTEM_DEFAULT, LCMAP_FULLWIDTH, halfWidth, -1, sb, sb.Capacity);
        return sb.ToString();
    }

    [DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
    private static extern int LCMapString(uint Locale, uint dwMapFlags, string lpSrcStr, int cchSrc, StringBuilder lpDestStr, int cchDest);
}

否则,您可以构建一个字典作为查找 table。

不是通用解决方案,但在我的特定情况下(半角日文片假名 ラーメン 到全角片假名 ラーメン),String#Normalize 和 NFKC 选项完成了这项工作。

该方法与VB不兼容(例如它将全角数字42转换为半角数字42),因此您需要select characters 替换为:

// Half-width katakana to Full-width katakana
cDataString = new Regex(@"[\uFF61-\uFF9F]+").Replace(cDataString, (m) => m.Value.Normalize(NormalizationForm.FormKC));