如何在没有明确分隔符的情况下解析键值字符串

本文关键字:情况下 字符串 键值 分隔符 | 更新日期: 2024-09-20 08:22:06

我正在编写一个控制3D打印机的小程序。当我向它发送一些东西时,它通常会以ok作为响应,但如果有些东西不好,它会发送这样的东西:

 T:221.0 /220.0 @:0 W:1

如果它有合适的分隔符,我可以很容易地解析它,但由于字符串221.0 /220.0,使用空格是不可靠的。因此,如果我使用空格作为分隔符,则/220.0可以被视为键值对,但由于它在T之下,因此没有键。我计划得到每个冒号的索引和后面的简单起始1个字符,但键的长度也是可变的。例如:

 T:221.0 /220.0 B@:127 @:0 W:1

B@现在有两个字符长。

我做了一些研究,但我发现所有的东西都有合适的分隔符,比如带有数据的URL。

http://www.niederschlagsradar.de/images.aspx?jaar=-6&type=europa.cld&datum=201311161500&cultuur=en-GB&continent=europa

我计划获取每个冒号的索引,然后在找到冒号时向后搜索一个空格,这将作为起点。同样,下一个键值对的起点将作为上一个键值的终点。但是,我不确定这是否是正确的方法。

主要问题:如何在没有正确分隔符的情况下解析字符串我并没有什么特别的要求。无论是一个数组还是一个列表,将键和值的变量分开,或者将所有内容都放入一个数组中,这样

string[] data = {key1,value1,key2,value2,key3,value3};

更新:以下是第二个示例中的键值对:

Key:Value
  T:221.0 /220.0
 B@:127
  @:0
  W:1

更多样品:

 T:221.0 /220.0 B:85.7 /120 B@:30W @:0 W:8
Key:Value
T:221.0 /220.0
B:85.7 /120
B@:30W
@:0
W:8

这是另一个更复杂的:

 T:171.4 /220.0 B:90.3 /120 T1:171.4 /220.0 B@:30 @:12W W:6
Key:Value
T:171.4 /220.0   // Temperature of first nozzle heater
B:90.3 /120      // Temperature of the hot plate it's printing on
T1:171.4 /220.0  // Temperature of the second nozzle heater if it exists
B@:30            // Raw power consumption of hotbed (unit depends on config)
@:12W            // Power of of nozzle in Watts (unit depends on config)
W:6              // Waiting time (in seconds). If the optimal conditions are met and this counts down to zero, printing resumes. Else, reset to 10.

示例字符串开头的空格是有意的。它确实是从一个空格开始的。对于那些感兴趣的人来说,这些是运行马林3D打印固件的Arduino Mega的回复。这些是当打印机加热器还不够热,无法挤出时的回复。

相关:如何解析字符串以在其中找到键值对

如何在没有明确分隔符的情况下解析键值字符串

我会使用以下逻辑:

  1. 按冒号拆分
  2. 第一项永远是第一把钥匙
  3. 最后一项总是最后一个值
  4. 对于每个中间项(从第二项开始),检查最后一个空格的索引。最后一个空格之前的所有内容都是最新密钥的值,右边的所有内容是下一个密钥

代码:

private List<KeyValuePair<string, string>> ParsePrinterResponse(string rawResponse)
{
    List<KeyValuePair<string, string>> pairs = new List<KeyValuePair<string, string>>();
    string[] colonItems = rawResponse.Trim().Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
    if (colonItems.Length > 1)
    {
        string currentKey = colonItems[0], currentValue = "";
        for (int i = 1; i < colonItems.Length; i++)
        {
            string currentItem = colonItems[i];
            int spaceIndex = currentItem.LastIndexOf(" ");
            if (spaceIndex < 0)
            {
                //end of string, whole item is the value
                currentValue = currentItem;
            }
            else
            {
                //middle of string, left part is value, right part is next key
                currentValue = currentItem.Substring(0, spaceIndex);
            }
            pairs.Add(new KeyValuePair<string, string>(currentKey, currentValue));
            currentKey = currentItem.Substring(spaceIndex + 1);
        }
    }
    return pairs;
}

使用示例:

errorBox.Lines = ParsePrinterResponse("T:171.4 /220.0 B:90.3 /120 T1:171.4 /220.0 B@:30 @:12W W:6").ConvertAll(p =>
{
    return string.Format("{0}:{1}", p.Key, p.Value);
}).ToArray();
From each colon position found,
    search backwards until a whitespace character is found
    search forward until a whitespace character is found

我不会将下一个键值对的起始点与上一个结束点联系起来,因为键值对之间可能有几个空格。我将只从冒号位置开始确定键和值。

相关文章: