如何安全地拆分字符串?

时间:2010-10-18 12:48:43

标签: c# .net-3.5 string

当我们想要出于任何原因分割sting时,我们(至少我自己)倾向于使用(管道)|字符进行拆分,因为很少找到某人或该应用程序使用它在一个字符串上...但如果它使用会发生什么?

好吧,会抛出一个简单的崩溃:)

我发现大学使用non-printable字符来执行相同的技术,例如:

String.Format(
         "{1}{0}{2}{0}{3}{0}{4}",
         (char)2,
         myFirstString,
         mySecondString,
         myThirdString,
         myFourthString);

当我们想要将孔串提取到它的部分

String.Split((char)2);

这样安全吗? 我应该采用这种安全分割字符串的方法吗? 还有其他安全技术吗?

6 个答案:

答案 0 :(得分:8)

它可能比管道“更安全”,因为它更少,但两种方式都不是最理想的,因为它们将你限制在可能的字符串的子集中。

考虑使用正确的编码 - 明确地编码任意字符串列表。最简单的编码可能只是序列化string[]。您可以使用BinaryFormatterXmlSerializer或其他内容。

如果结果 是一个字符串,并且它必须是 short ,那么你可以尝试这样的事情:

  • 编码:(单个字符串的字符串列表)
    • 在每个字符串中将每个!替换为!e,将每个|替换为!p。现在,没有一个字符串包含|,您可以轻松地将其反转。
    • 使用|作为分隔符连接字符串。
  • 解码:(单个字符串返回字符串列表)
    • 拆分|字符。
    • 在每个字符串中将所有!p替换为|,将!e替换为!。这会恢复原始字符串。

答案 1 :(得分:3)

这实际上是以这种格式生成字符串的应用程序与消费字符串的应用程序之间的契约 - 使用适合您情况的任何内容。

您可能想要考虑是否首先将多个字符串展平为单个巨型字符串。如果它们存在的原因仅仅是为了在您的应用程序中表示“分离的”文本数据,您可能希望将数据生成为一系列字符串(例如,string[])一开始。在这种情况下,不需要“解析”。

另一方面,如果数据必须持久并在以后消耗,则有几个选项。例如:

  1. 数据库:将每个字符串作为一行存储在数据库表中。不需要拆分。
  2. 指定分隔符:将字符串存储在带有“特殊”分隔符的平面文件中,该分隔符表示当前字符串的结尾。显然,这个字符必须是不能成为合法子字符串的一部分。例如。如果你的字符串不能像你说的那样包含管道字符,那么这是分隔符的合理选择。
  3. 转义序列:例如*是分隔符,**表示字符串中的星号。这意味着没有保留任何字符用作哨兵(使其无法代表)。在缺点方面,解析变成了一项非常重要的任务。
  4. 专用格式:例如XML。当你认为这需要“转义”某些字符时,这实际上是第3点的扩展,但问题现在已经被你的XML库所驱使了。

答案 2 :(得分:2)

如果你能提供帮助,最好永远不要将字符串连接在一起。像这样分裂是代码味道。

当然,使用控制角色“更有可能”没有问题,但它仍然不完美。如果您真的必须这样做,请使用NUL(\0)。这个角色至少有一个字符串哨兵的历史。

答案 3 :(得分:2)

我认为使用不可打印的字符比安全更容易。 如果您想要安全,解决方案是序列化/反序列化您的List<string>

答案 4 :(得分:1)

您可以使用普通的CSV读写器。这有助于您,因为当值具有分隔符时,它用双引号括起来:

a,b,"c,d"

产生

new[] { "a", "b", "c,d" }

这可能有助于http://www.codeproject.com/KB/database/CsvReader.aspx

答案 5 :(得分:0)

这取决于字符串的预期内容。如果预期的字符串可能具有不可打印的字符,则可能不是。另一种方法是逃避你将分裂的字符串,它看起来更多的工作,但可以放入一个可重用的帮助器:

var string1 = "string|1";
var string2 = "string |2";
var string3 = "string| 3";
var string4 = "string | 4";

var stringToSplit = MergeStrings(string1, string2, string3, string4);

var results = SplitString( stringToSplit );

foreach(string result in results)
{
    Trace.WriteLine( result );
}

使用以下方法。

public string MergeStrings(params string[] strings)
{
    var stringBuilder = new StringBuilder();

    foreach(var s in strings)
    {
        stringBuilder.Append( s.Replace( "|", "||" ) );
        stringBuilder.Append( " | " );
    }

    return stringBuilder.ToString();
}

public IEnumerable<string> SplitString(string stringToSplit)
{
    var results = stringToSplit.Split( new[] { " | " }, StringSplitOptions.RemoveEmptyEntries );

    return results.Select( result => result.Replace( "||", "|" ) );
}

您可能希望自定义分隔符。