有没有一种简单的方法来解析C#中的结构化文本文件?

时间:2017-02-28 15:47:28

标签: c# file parsing

我试图解析一个文本文件,但我觉得必须有一个更好的方法来实现它。

文本文件由项目组成,这些项目既可以包含键值对,也可以包含其他项目。我相信该文件只会像孙项目一样深(例如项目中的项目,项目内)。

目前我正在逐行遍历文件,并跟踪我的深度。然后,当我到达终止字符('}')并且我在0级时,我知道我已经捕获了整个父项。

由于我不认为我已经解释得很好,我的文件结构看起来与此类似。

parent_item {
key: value
key: value
child_item {
    key: value
    key: value
}
child_item {
    key: value
    key: value
    key: value
    grandchild_item {
        key: value
        key: value
    }
}
key: value
key: value
}
parent_item {
    key: value
    key: value
    child_item {
        key: value
        key: value
    }
}

每个项目可以有0到多个子项目,但我认为它不会超过3个级别(父级 - >孩子 - >孙子级)。

是否有更简单的方法来解析这个问题,还是我正朝着正确的方向努力?

5 个答案:

答案 0 :(得分:3)

您的文件看起来几乎像JSON,除了复杂嵌套对象的属性名称之间没有冒号。但是,它不同,您将无法使用JSON.NET之类的JSON解析器。

我建议像你一样手动解析它 - 但是使用堆栈和状态机。每次遇到开放的卷曲{时,您的状态机都应该推送到堆栈,并在收到卷曲}时从堆栈弹出。

答案 1 :(得分:1)

与JSON非常相似,如果格式是常量(打开卷曲'{'和结束卷曲}作为行中的最后一个字符),您可以将该文本转换为JSON并进行微小更改。 警告,未经过测试,例如

StringBuilder jsonEncoded = new StringBuilder();
string[] lines = content.Split("\n");
foreach(string line in lines)
{
    if(line.EndsWith("{") || line.EndsWith("}")
        jsonEncoded.AppendLine(line);
    else
        jsonEncoded.AppendLine(line + ",");
}

之后,常规JSON Deseralization将起作用。

答案 2 :(得分:1)

如果您可以信任您的源代码而不弄乱此架构,您可以编写一个解决方法。我有一些想法:

JSON

看起来像是json。也许你可以规范化它,然后用JSON.NET解析它。

我只是写了一个丑陋但有效的解决方案。试试here

using System;
using System.Text.RegularExpressions;

public class Program
{
    public static string Quoterize(string s)
    {
        return Regex.Replace(s, @"\w+", match => "\"" + match + "\"");
    }

    public static string RewriteThisPlease(string s)
    {
        return s
            .Replace("\n", "," + Environment.NewLine)
            .Replace(" ", "")
            .Replace(Environment.NewLine, "")
            .Replace("{,", "{")
            .Replace(",}", "}");
    }

    public static void Main()
    {
        var k = @""; // your file goes here
        Console.WriteLine("{"+MoveToRegexPlease(Quoterize((k).Replace("{", ": {")))+"}");
    }
}

YAML

看起来像是json。它看起来更像是yaml。在两个简单替换之后,yaml验证器将接受您的文件:

// where k is your file as string
Console.WriteLine(k.Replace("{\n", ":\n").Replace("}",""));

Demo

自制

看起来像是json。你会在那里找到很多JSON解析器,也许你可以分叉并调整它以适应你的情况。

作业

看起来像是json。你会发现很多JSON解析器教程。编写一个小解析器总是一个很好的练习。

祝你好运!

答案 3 :(得分:0)

以下是使用RegEx和Balancing Group Definitions

的简短示例(尽管尚未经过仔细测试)

此示例使用链接中的代码。我只是替换括号而不是更改代码并按原样使用它:

static void Main(string[] args)
{
    // here I read your posted file
    string input = System.IO.File.ReadAllText("test.txt");

    input = input.Replace('{', '<');
    input = input.Replace('}', '>');

    string pattern = "^[^<>]*" +
              "(" +
              "((?'Open'<)[^<>]*)+" +
              "((?'Close-Open'>)[^<>]*)+" +
              ")*" +
              "(?(Open)(?!))$";

    //string input = "<abc><mno<xyz>>";

    Match m = Regex.Match(input, pattern);
    if (m.Success == true)
    {
        Console.WriteLine("Input: \"{0}\" \nMatch: \"{1}\"", input, m);
        int grpCtr = 0;
        foreach (Group grp in m.Groups)
        {
            Console.WriteLine("   Group {0}: {1}", grpCtr, grp.Value);
            grpCtr++;
            int capCtr = 0;
            foreach (Capture cap in grp.Captures)
            {
                Console.WriteLine("      Capture {0}: {1}", capCtr, cap.Value);
                capCtr++;
            }
        }
    }
    else
    {
        Console.WriteLine("Match failed.");
    }   

    Console.ReadKey();
}

将其粘贴到一个新的控制台项目中,让它运行并查看输出。它在开始时很混乱,但它可能会让你根据自己的需要调整它。

答案 4 :(得分:-1)

使用序列化。

在C#中,您可以轻松使用JSON或XML序列化。

JSON: https://msdn.microsoft.com/en-us/library/bb412179(v=vs.110).aspx

更好的方法是XML,因为它更灵活,并且在C#中有更好的支持: https://msdn.microsoft.com/en-us/library/58a18dwa(v=vs.110).aspx