考虑转义字符的情况下,按分号拆分字符串

3

非常简单的问题:

我想将连接字符串拆分成关键字/值对,例如以下连接字符串:

Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=vm-jp-dev2;Data Source=scsql\sql2005;Auto Translate=False

Would become:

Provider=SQLOLEDB.1
Integrated Security=SSPI
Persist Security Info=False
Initial Catalog=vm-jp-dev2
Data Source=scsql\sql2005
Auto Translate=False

问题在于 MSDN文档 明确说明,如果连接字符串的值被单引号或双引号包含,则允许包含分号(所以如果我理解正确,以下内容是有效的):

Provider="Some;Provider";Initial Catalog='Some;Catalog';...

什么是在C#中拆分此字符串的最佳方法?
4个回答

9
有一个名为 DBConnectionStringBuilder 的类可以满足您的需求...
        System.Data.Common.DbConnectionStringBuilder builder = new System.Data.Common.DbConnectionStringBuilder();

        builder.ConnectionString = "Provider=\"Some;Provider\";Initial Catalog='Some;Catalog';";

        foreach (string key in builder.Keys)
        {
            Response.Write(String.Format("{0}: {1}<br>", key , builder[key]));
        }

谢谢,我以为可能会有这样的东西,但我找不到它! - Justin

0
你应该实现一些简单的字符串解析,尊重引号。例如:
public static IEnumerable<string> SplitString(string str)
{
    int StartIndex = 0;
    bool IsQuoted = false;
    for (int I = 0; I < str.Length; I++)
    {
        if (str[I] == '"')
            IsQuoted = !IsQuoted;
        if ((str[I] == ';') && !IsQuoted)
        {
            yield return str.Substring(StartIndex, I - StartIndex);        
            StartIndex = I + 1;
        }
    }

    if (StartIndex < str.Length)
        yield return str.Substring(StartIndex);
}

0
你可以编写一个小型解析器。在字符串中移动时跟踪引用状态,这样通常更可靠。
另一种选择是使用正则表达式,并匹配整个内容,可以在 regex.Split 中捕获而不是跳过输出:
var re = new Regex(@"([\w\s]+=\s*?(?:['""][\w\s]+['""]|[\w\s]+));");
var parts = re.Split(connectionString)

这里假设:

  • 无法在引号内引用引号(或其他方式)
  • 名称内容仅限于空格和字母数字字符(将 [\s\w] 替换为覆盖有效字符的组)。

个人认为,如果我不能很快地解决正则表达式问题,我会选择解析器。

编辑:有一种更简单的方法。 DbConnectionStringBuilder 实现了 IEnumerable,因此让它来完成工作:

using System;
using System.Collections.Generic;
using System.Data.Common;

class Program {
    static void Main(string[] args) {
        string conStr = @"Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=vm-jp-dev2;Data Source='scsql\sql;2005';Auto Translate=False";

        var cb = new DbConnectionStringBuilder();
        cb.ConnectionString = conStr;
        int n = 0;
        foreach (KeyValuePair<string, object> c in cb) {
            Console.WriteLine("#{0}: {1}={2}", ++n, c.Key, c.Value);
        }
    }
}

0

如果是SQL Server,你可以简单地这样做:

SqlConnectionStringBuilder decoder = new SqlConnectionStringBuilder(connectionString);

string UserID = decoder.UserID; 
string Password = decoder.Password; 

等等。


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