从 C# 中的分隔文件中读取行

Reading Lines From Delimited File in C#

我有一个程序,我试图在其中获取他们输入程序的信息并将其存储到各种模板文件中,以便可以轻松保存和重新加载。模板格式如下所示

#START#1 -- Contact#END#
#START#1 -- Error
2 -- Error
3 -- Error#END#
#START#1 -- Actions
2 -- Actions
3 -- Actions
4 -- Actions#END#
#START#1 -- Res
2 -- Res
3 -- Res#END#
#START#WorkedWith#END#
#START#3011#END#
#START#1 -- Details
2 -- Details
3 -- Details#END#

#START##END# 标签之间的所有内容都是需要存储在不同变量中的值。

例如第一个变量需要包含

1 -- Contact

第二个变量需要包含

1 -- Error
2 -- Error
3 -- Error

以此类推,直到第 7 个变量包含第二个详细信息。

读取文件并将分隔符之间的数据存储到变量中的最简单方法是什么?

提前致谢!

编辑:樱花

代码:

string sInput = "";
using (var reader = new StreamReader(sTemplateFilePath))
{
    while (!reader.EndOfStream)
    {
        var line = reader.ReadLine();
        sInput = sInput + line;

    }
    reader.Close();
}
foreach (Match m in Regex.Matches(sInput, "#START#(.*?)#END#", RegexOptions.Singleline | RegexOptions.Compiled))
{
    foreach (var line in m.Groups[1].Value.Split('\n'))
    {
        switch (iLineCount)
        {
            case 0:
                sContactReason = line;
            break;

            case 1:
                sError = line;
            break;

            case 2:
                sActionsTaken = line;
            break;

            case 3:
                sResolution = line;
            break;

            case 4:
                sL3 = line;
            break;

            case 5:
                sKB = line;
            break;

            case 6:
                sDetails = line;
            break;
        }

        iLineCount++;

    }
}

输出:

1 -- Contact

1 -- Error2 -- Error3 -- Error

1 -- Actions2 -- Actions3 -- Actions4 -- Actions

1 -- Res2 -- Res3 -- Res

WorkedWith

3011

1 -- Details2 -- Details3 -- Details

我可能会使用带有捕获组的 Regex class 来获取 #BEGIN##END# 分隔符之间的内容。我猜你想以其他方式丢弃文本。正则表达式类似于:

#BEGIN#(.*?)#END#

捕获组 (#1) 由括号指示,并将包含分隔文本。您可以通过将内容加载到字符串缓冲区来遍历内容,并在没有剩余匹配项时终止此正则表达式。

    static void Main()
    {
        string s = @"#START#1 -- Contact#END#
#START#1 -- Error
2 -- Error
3 -- Error#END#
#START#1 -- Actions
2 -- Actions
3 -- Actions
4 -- Actions#END#
#START#1 -- Res
2 -- Res
3 -- Res#END#
#START#WorkedWith#END#
#START#3011#END#
#START#1 -- Details
2 -- Details
3 -- Details#END#";

        int k = -1;
        foreach (Match m in Regex.Matches(s, "#START#(.*?)#END#", RegexOptions.Singleline | RegexOptions.Compiled))
        {
            Console.WriteLine("Variable " + ++k + " is:\n" + m.Groups[1].Value);
            Console.WriteLine();
        }
        Console.ReadLine();
    }

"#START#(.*?)#END#" 将为您匹配 #START##END#" 之间的任何内容。

结果:

Variable 0 is:
1 -- Contact

Variable 1 is:
1 -- Error
2 -- Error
3 -- Error

Variable 2 is:
1 -- Actions
2 -- Actions
3 -- Actions
4 -- Actions

Variable 3 is:
1 -- Res
2 -- Res
3 -- Res

Variable 4 is:
WorkedWith

Variable 5 is:
3011

Variable 6 is:
1 -- Details
2 -- Details
3 -- Details

如果你想将结果拆分成行,你可以使用 split 来获得所需的变量。

int k = -1;
foreach (Match m in Regex.Matches(s, "#START#(.*?)#END#", RegexOptions.Singleline | RegexOptions.Compiled))
{
    k++;
    int k2 = -1;
    Console.WriteLine("Variable " + k + ":");
    foreach (var line in m.Groups[1].Value.Split('\n'))
    {
        Console.WriteLine("Line " + ++k2 + ": " + line);
    }
    Console.WriteLine();
}

结果:

Variable 0:
Line 1: 1 -- Contact

Variable 1:
Line 1: 1 -- Error
Line 3: 2 -- Error
Line 5: 3 -- Error

Variable 2:
Line 1: 1 -- Actions
Line 3: 2 -- Actions
Line 5: 3 -- Actions
Line 7: 4 -- Actions

Variable 3:
Line 1: 1 -- Res
Line 3: 2 -- Res
Line 5: 3 -- Res

Variable 4:
Line 1: WorkedWith

Variable 5:
Line 1: 3011

Variable 6:
Line 1: 1 -- Details
Line 3: 2 -- Details
Line 5: 3 -- Details

编辑:

下面的整个代码都是浪费,而且是错误的。

string sInput = "";
using (var reader = new StreamReader(sTemplateFilePath))
{
    while (!reader.EndOfStream)
    {
        var line = reader.ReadLine();
        sInput = sInput + line;

    }
    reader.Close();
}

改为:

string sInput = File.ReadAllText(sTemplateFilePath);

编辑

@Sakura I need to assign each Regex match to a different variable. So the first match goes into Variable1, the second match goes in Variable2, the third match goes in Variable3. Does that make sense? –

这是你需要的吗?

int k = 0;
foreach (Match m in Regex.Matches(sInput, "#START#(.*?)#END#", RegexOptions.Singleline | RegexOptions.Compiled))
{
    k++;
    switch (k)
    {
        case 1:
            var1 = m.Groups[1].Value;
            break;
        case 2:
            //var2...
            break;
    }
    foreach (var line in m.Groups[1].Value.Split('\n'))
    {
        switch (iLineCount)
        {
        }
    }
}

使用 CSV 文件。它们实际上是为您正在尝试做的事情而制作的。如果您不想使用逗号,您始终可以通过在文件中指定其他属性来更改分隔符。

您可以使用行来分隔倍数,就像您在 post 中的自定义分隔符之间所做的那样。如果我遗漏了什么,我深表歉意。

编写您自己的解析器。这真的很简单。在这里,我假设 #START##END# 各占一行(您可以使用搜索和替换或 C# 代码强制执行)

    private List<List<string>> parseData(string data)
    {
        List<List<string>> allValues = new List<List<string>>();
        List<string> currentValues = null;

        // Assume that each line has only one entry
        foreach (var line in data.Split(new [] {"\r\n"}, StringSplitOptions.RemoveEmptyEntries))
        {
            if (line == "#START#")
            {
                currentValues = new List<string>();
            }
            else if (line == "#END#")
            {
                allValues.Add(currentValues);
            }
            else
            {
                currentValues.Add(line);
            }
        }
        return allValues;
    }

与指向正则表达式或编写您自己的解析器的其他答案相反,我想建议使用 FileHelpers library

读取带分隔符的文件看起来像这样;首先定义一个class匹配单个文件记录:

[DelimitedRecord("|")]
public class Orders
{
    public int OrderID;

    public string CustomerID;

    [FieldConverter(ConverterKind.Date, "ddMMyyyy")]
    public DateTime OrderDate;

    [FieldConverter(ConverterKind.Decimal, ".")] // The decimal separator is .
    public decimal Freight;
}

正在读取文件:

var engine = new FileHelperEngine<Orders>();
var records = engine.ReadFile("Input.txt");

foreach (var record in records)
{
    Console.WriteLine(record.CustomerID);
    Console.WriteLine(record.OrderDate.ToString("dd/MM/yyyy"));
    Console.WriteLine(record.Freight);
}