PRinCEKtd
PRinCEKtd

Reputation: 270

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

Recently I came across this code in a C# application.

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

I understand that the StrConv is a string function of VB. You can call it by including 'using Microsoft.VisualBasic;'.

It is supposed to covert half width japanese characters into full width ones.

My question is: Is there a way to achieve the same WITHOUT using the VB functions and WITHOUT including the VB headers, using only the standard c# functions? I know there are many c# string conversion functions and some of them can convert from unicode to ansi and vice versa and so on. But I am not sure if any of those will directly get the exact same result as the above VB one. So, can this be done in c#?

Thank you for your time and efforts.

Update: I came across this question that was asked 5 years ago. The answers and discussions do show some ways in which it could be done. What I would specifically like to know is that, after 5 years and new versions and what nots, is there a simpler and better way to do this in .NET without depending on VB functions or VB libraries?

Upvotes: 3

Views: 5970

Answers (2)

snipsnipsnip
snipsnipsnip

Reputation: 2575

Not a generic solution, but in my particular case (Half-width Japanese katakana ラーメン to Full-width katakana ラーメン), String#Normalize with NFKC option did the job.

Note that this method is not entirely compatible with VB one (e.g. it converts full-width numbers 42 to half-width numbers 42), so you need to select characters to replace like:

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

Upvotes: 1

user6572277
user6572277

Reputation:

There is no equivalent function in C#.

If you follow the source code for Microsoft.VisualBasic.dll's StrConv, you'll see it actually p/invokes LCMapString internally similar to the answer you linked.

If you don't want to reference Microsoft.VisualBasic.dll, you could wrap the p/invoke into a helper class or service written in C#, something like this...

// NOTE: CODE NOT TESTED
// Code from John Estropia's StackOverflow answer
// https://stackoverflow.com/questions/6434377/converting-zenkaku-characters-to-hankaku-and-vice-versa-in-c-sharp

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);
}

Otherwise, you could build a Dictionary to act as a look-up table.

Upvotes: 2

Related Questions