如何将多行字符串转换为C#字符串集合或将C#字符串集合转换为多行字符串?

7

在Windows API中,多字符串(由空字符分隔的双重空终止字符串)很常见。将从API返回的多字符串转换为C#字符串集合以及反过来的好方法是什么?

我特别关注字符编码的正确处理(Windows XP及更高版本)。

下面的方法似乎对于创建多个字符串而言还可以,但我没有解码多字符串的示例。

static string StringArrayToMultiString(
    ICollection<string> stringArray
    )
{
    StringBuilder multiString = new StringBuilder();


    if (stringArray != null)
    {
        foreach (string s in stringArray)
        {
            multiString.Append(s);
            multiString.Append('\0');
        }
    }

    return multiString.ToString();
}
3个回答

9
这可能有些天真,但是怎么样:
static string[] MultiStringToArray(string multiString)
{
    return multiString.TrimEnd('\0').Split('\0');
}

同时 - 在StringArrayToMultiString函数中,你是否漏掉了最后一个\0(您声明了双 null 结尾)? 如果该数组是 params string[] 数组,那么调用起来可能会更容易 - 类似于:

    static string StringArrayToMultiString(params string[] values)
{
    if (values == null) throw new ArgumentNullException("values");
    StringBuilder multiString = new StringBuilder();

    foreach (string s in values)
    {
        multiString.Append(s);
        multiString.Append('\0');
    }
    return multiString.ToString();
}

[在澄清关于最终\0之后进行编辑]


1
当字符串通过COM发送时,我认为\0已经存在于字符串中,这意味着他需要一个\0但不需要另一个。 - configurator
1
是的,没错——当一个字符串被传递给Win32 API时,它是以空字符结尾的。因此不需要添加最后的\0。一个多字符串不能包含空字符串。这意味着一个普通的空字符串""是一个合法的没有条目的多字符串。 - k...m
如果multiString值包含完整的多字符串值,MultiStringToArray()方法可以很好地工作,但问题在于如何从API调用中获取该值。 - k...m
2
这里的TrimEnd可以被省略,因为在双null终止列表中不能存储空字符串,所以可以使用multiString.Split('\0', StringSplitOptions.RemoveEmptyEntries) - configurator

3
我已经测试了StringArrayToMultiString方法,并使用ChangeServiceConfig()函数更改Windows服务的依赖项,对于零个、一个和多个字符串都可以很好地工作。
同时,我已经找到了解码从API调用接收到的多字符串的解决方案。例如,SCardListReaders()函数返回PC/SC读卡器名称的多字符串。我将其声明为:
[DllImport("winscard.dll", CharSet = CharSet.Auto)]
static extern int SCardListReaders(
    IntPtr context,
    string groups,
    char[] readers,
    ref uint readersLen
    );

请注意,返回多个字符串的readers参数被声明为char[]。返回值可以轻松地解析并转换为字符串集合:
static string[] MultiStringToArray(
    char[] multistring
    )
{
    List<string> stringList = new List<string>();
    int i = 0;
    while (i < multistring.Length)
    {
        int j = i;
        if (multistring[j++] == '\0') break;
        while (j < multistring.Length)
        {
            if (multistring[j++] == '\0')
            {
                stringList.Add(new string(multistring, i, j - i - 1));
                i = j;
                break;
            }
        }
    }

    return stringList.ToArray();
}

1
在RegistryKey.SetValue()和RegistryKey.GetValue()的MSDN文档中,示例仅传递或强制转换为string[]。这样做有问题吗?

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接