我试图解析一个文本文件,但我觉得必须有一个更好的方法来实现它。
文本文件由项目组成,这些项目既可以包含键值对,也可以包含其他项目。我相信该文件只会像孙项目一样深(例如项目中的项目,项目内)。
目前我正在逐行遍历文件,并跟踪我的深度。然后,当我到达终止字符('}')并且我在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个级别(父级 - >孩子 - >孙子级)。
是否有更简单的方法来解析这个问题,还是我正朝着正确的方向努力?
答案 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.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("{", ": {")))+"}");
}
}
看起来像是json。它看起来更像是yaml。在两个简单替换之后,yaml验证器将接受您的文件:
// where k is your file as string
Console.WriteLine(k.Replace("{\n", ":\n").Replace("}",""));
看起来像是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