我有一个问题,我想知道是否有任何聪明的解决方法。
我需要通过套接字将字符串传递给 Web 应用程序。该字符串由三个部分组成,我使用“|” 作为分隔符,在接收应用程序处拆分为三个单独的部分。
问题是'|' character 可以是 3 个单独字符串中的任何一个中的一个字符,当这种情况发生时,整个拆分操作会扭曲字符串。
因此,我的问题是:有没有办法在某些文本中使用字符/字符串作为分隔符,而该字符/字符串本身可能在文本中?
一般模式是转义分隔符。例如当'|' 是分隔符,你可以使用“||” 每当您需要字符串中的字符本身时(如果您允许空字符串可能会很困难),或者您可以使用类似 '\' 作为转义字符,以便 '|' 变成“\|” 而“\”本身就是“\\”
有没有办法在某些文本中使用字符/字符串作为分隔符,而该字符/字符串本身可能在文本中?
简单的回答:没有。
这当然是在字符串/分隔符完全相同的情况下,无需对文本进行修改。
当然有可能的解决方法。一种可能的解决方案是,您可能希望分隔符之间具有最小/固定宽度,但这并不完美。
另一种可能的解决方案是选择一个在文本中永远不会同时出现的分隔符(字符序列)。这需要您更改源和消费者。
当我需要使用分隔符时,我通常会选择一个我 99.9% 肯定不会出现在普通文本中的分隔符,分隔符可能会根据我期望的文本类型而有所不同。
这是维基百科的引述:
由于分隔符冲突是一个非常普遍的问题,因此人们发明了各种避免它的方法。一些作者可能会尝试通过选择不太可能出现在数据流本身中的分隔符(或字符序列)来避免该问题。这种临时方法可能是合适的,但它必然依赖于对数据流中将出现的内容的正确猜测,并且不提供针对恶意冲突的安全性。因此也适用其他更正式的约定。
只是对您的用例的一个附注,为什么不对发送的数据使用协议呢?比如protobuf?
这里的问题是给定以下字符串:
string toParse = "What|do you|want|to|say|?";
它可以通过多种方式解析:
“
你
想要|要|说什么|?”
或者
“什么|你
想说
|说|?”
等等...
你可以定义规则来解析你的字符串,但是编码它会很困难,而且它对最终用户来说似乎是违反直觉的。
字符串必须包含一个转义字符,指示符号“|” 是想要的,而不是分隔符。例如,这可能是“\|”。
这是使用正则表达式的完整示例:
using System.Text.RegularExpressions;
//... Put this in the main method of a Console Application for instance.
// The '@' character before the strings are to specify "raw" strings, where escape characters '\' are not escaped
Regex reg = new Regex(@"^((?<string1>([^\|]|\\\|)+)\|)((?<string2>([^\|]|\\\|)+)\|)(?<string3>([^\|]|\\\|)+)$");
string toTest = @"user\|dureuill|deserves|an\|upvote";
MatchCollection matches = reg.Matches(toTest);
if (matches.Count != 1)
{
throw new FormatException("Bad formatted pattern.");
}
Match match = matches[0];
string string1 = match.Groups["string1"].Value.Replace(@"\|", "|");
string string2 = match.Groups["string2"].Value.Replace(@"\|", "|");
string string3 = match.Groups["string3"].Value.Replace(@"\|", "|");
Console.WriteLine(string1);
Console.WriteLine(string2);
Console.WriteLine(string3);
Console.ReadKey();
您可以找到消息部分中不存在的分隔符,而不是|
用作分隔符,并将其传递到已发送消息的开头。这是一个使用整数作为分隔符的示例:
String[] parts = {"this is a message", "it's got three parts", "this one's the last"};
String delimiter = null;
for (int i = 0; i < 100; i++) {
String s = Integer.toString(i);
if (parts[0].contains(s) || parts[1].contains(s) || parts[2].contains(s))
continue;
delimiter = s;
break;
}
String message = delimiter + "#" + parts[0] + delimiter + parts[1] + delimiter + parts[2];
现在消息是0#this is a message0it's got three parts0this one's the last
。
在接收端,您首先找到分隔符并在其上拆分消息字符串:
String[] tmp = message.split("#", 2);
String[] parts = tmp[1].split(tmp[0]);
这不是最有效的解决方案,因为它需要多次扫描消息部分,但它很容易实现。如果您没有找到值delimiter
并且null
恰好是消息的一部分,您可能会遇到意外的结果。
也许首先对您的字符串进行 HTMLEncode 和 HTMLDecode 很有用,然后将它们与您的分隔符一起附加。
我想你要么
1) 一起找出一个永远不会出现在字符串中的字符或一组字符
或者
2)使用固定长度的字符串和填充。
如果您可以灵活地执行此操作,也许可以调整分隔符?因此,字符串可以读取“String1”|“String2”,而不是 String1|String2。
如果不需要管道 - 在创建/输入此字符串期间进行一些简单的验证?