在C#中解析文本文件并跳过一些内容

时间:2009-05-06 19:17:51

标签: c# .net file-io text-parsing

我正在尝试解析具有标题和正文的文本文件。在此文件的标题中,有对主体部分的行号引用。例如:

SECTION_A 256
SECTION_B 344
SECTION_C 556

这意味着,SECTION_A从第256行开始。

将此标题解析为字典的最佳方法是什么,然后在必要时阅读这些部分。

典型的情况是:

  1. 解析标题并只读部分SECTION_B
  2. 解析标题并阅读每个部分的第一段。
  3. 数据文件非常大,我绝对不想将所有内容加载到内存中,然后对其进行操作。

    我很感激你的建议。我的环境是VS 2008和C#3.5 SP1。

5 个答案:

答案 0 :(得分:3)

你可以很容易地做到这一点。

问题分为三个部分。

1)如何查找文件中某一行的起始位置。执行此操作的唯一方法是从文件中读取行,保留一个列表,该列表记录该行文件中的起始位置。 e.g

List lineMap = new List();
lineMap.Add(0);    // Line 0 starts at location 0 in the data file (just a dummy entry)
lineMap.Add(0);    // Line 1 starts at location 0 in the data file

using (StreamReader sr = new StreamReader("DataFile.txt")) 
{
    String line;
    int lineNumber = 1;
    while ((line = sr.ReadLine()) != null)
        lineMap.Add(sr.BaseStream.Position);
}

2)读取索引文件并将其解析为字典。

Dictionary index = new Dictionary();

using (StreamReader sr = new StreamReader("IndexFile.txt")) 
{
    String line;
    while ((line = sr.ReadLine()) != null)
    {
        string[] parts = line.Split(' ');  // Break the line into the name & line number
        index.Add(parts[0], Convert.ToInt32(parts[1]));
    }
}

然后在文件中找到一行,请使用:

int lineNumber = index["SECTION_B";];         // Convert section name into the line number
long offsetInDataFile = lineMap[lineNumber];  // Convert line number into file offset

然后在DataFile.txt上打开一个新的FileStream,Seek(offsetInDataFile,SeekOrigin.Begin)移动到行的开头,并使用StreamReader(如上所示)从中读取行。

答案 1 :(得分:2)

嗯,显然你可以将名字+行号存储到字典中,但这对你没有任何帮助。

嗯,当然,它会让你知道从哪一行开始读取,但问题是,文件中的哪一行是那行?要知道的唯一方法是从头开始并开始计算。

最好的方法是编写一个解码文本内容的包装器(如果你有编码问题)并且可以给你一个行号到字节位置类型的映射,那么你可以把那个行号,256,看看在字典中知道256行从文件中的位置10000开始,然后从那里开始阅读。

这是一次性处理情况吗?如果没有,您是否考虑将整个文件填充到本地数据库中,如SQLite数据库?这将允许您在行号和其内容之间进行直接映射。当然,该文件甚至会比原始文件大,而且您需要将数据从文本文件复制到数据库,因此无论如何都会产生一些开销。

答案 2 :(得分:0)

一次只读取一行文件并忽略数据,直到找到所需的数据。你不会有任何内存问题,但性能可能不会很好。您可以在后台线程中轻松完成此操作。

答案 3 :(得分:0)

读取文件直到标题的末尾,假设您知道它在哪里。拆分你存储在空格上的字符串,如下所示:

Dictionary<string, int> sectionIndex = new Dictionary<string, int>();
List<string> headers = new List<string>(); // fill these with readline

foreach(string header in headers) {
    var s = header.Split(new[]{' '});
    sectionIndex.Add(s[0], Int32.Parse(s[1]));
}

找到你想要的字典条目,记住文件中读取的行数,然后循环直到你达到该行号,然后读到你到达下一部分的起始行。我不知道你是否可以保证字典中键的顺序,所以你可能需要当前和下一部分的名字。

请务必进行一些错误检查,以确保您正在阅读的部分不在您正在阅读的部分之前,以及您可以想到的任何其他错误情况。

答案 4 :(得分:0)

您可以逐行读取,直到捕获到所有标题信息并停止(假设所有节指针都在标题中)。您可以使用部分和行号来稍后检索数据。

string dataRow = "";

try
{
    TextReader tr = new StreamReader("filename.txt");

    while (true)
    {
        dataRow = tr.ReadLine();
        if (dataRow.Substring(1, 8) != "SECTION_")
            break;
        else
            //Parse line for section code and line number and log values
            continue;
    }
    tr.Close();
}
catch (Exception ex)
{
    MessageBox.Show(ex.Message);
}