【问题标题】:Reading the next line using LINQ and File.ReadAllLines()使用 LINQ 和 File.ReadAllLines() 读取下一行
【发布时间】:2010-03-01 03:37:30
【问题描述】:

我有一个代表项目的文件,在一行中有项目 GUID,后跟 5 行描述该项目。

示例:

Line 1: Guid=8e2803d1-444a-4893-a23d-d3b4ba51baee name= line1 
Line 2: Item details = bla bla   
.  
.  
Line 7: Guid=79e5e39d-0c17-42aa-a7c4-c5fa9bfe7309 name= line7 
Line 8: Item details = bla bla    
.  
. 

我正在尝试首先访问此文件,以使项目的 GUID 符合使用 LINQ 提供的条件,例如其中 line.Contains("line1").. 这样我将获得整行,我将从那里提取 GUID,我想将此 GUID 传递给另一个应该“再次”访问文件的函数,找到该行(其中line.Contains("line1") && line.Contains("8e2803d1-444a-4893-a23d-d3b4ba51baee") 并从该行开始读取接下来的 5 行。

有什么有效的方法吗?

【问题讨论】:

  • 你能提供更多细节吗?我不明白您是否在谈论单个文件...
  • 我也想知道当我可以在 File.ReadAllLines() 上进行 LINQ 查询时是否可以获取行号,知道吗?
  • 文件是否经常更改?如果没有,将其转换为 XML 可能是值得的,然后在您的实际程序中使用 XML。当然,您仍然必须处理一次文件才能进行转换,但之后您可以使用任何各种 XML 库。如果内容经常变化,每次转换文件可能不划算。
  • 文件内容不变。它会像一个日志或什么的。但是,当我将它们显示在“aspx”页面中时,我仍然必须逐行浏览它们,因为我会将这些行链接到数据库条目“cmets”。
  • 您是否可能试图避免阅读整个文件并寻找一种只阅读您需要的内容的方法?除非你能回答这样的问题,否则这会很困难:第 5 项的第一行第一个字节的确切索引是多少?

标签: linq file text-parsing


【解决方案1】:

考虑到您需要做的事情以及数组中行的索引是仙女积分,我认为完全使用 LINQ 没有任何意义。我还建议一次完成所有事情 - 多次打开文件不会像只读取一次并立即处理它那样有效。只要文件的结构与您描述的一样,这不会很困难:

    private void GetStuff()
    {
        var lines = File.ReadAllLines("foo.txt");
        var result = new Dictionary<Guid, String[]>();
        for (var index = 0; index < lines.Length; index += 6)
        {
            var item = new
            {
                Guid = new Guid(lines[index]),
                Description = lines.Skip(index + 1).Take(5).ToArray()
            };
            result.Add(item.Guid, item.Description);
        }
    }

【讨论】:

  • 谢谢丹尼尔。在这种情况下我有点担心大文件,我的意思是从头到尾读取文件,有时正在处理的文件高达 20MB .. 有没有使用这种方式的性能问题?
  • 另一件事是,每一行带有 GUID 的都会有一个“类型”,并且每种类型都有不同的操作集。因此,我将从该行中找到类型,将其与类型列表进行比较,然后继续...我对文件中的每一行都这样做感觉不好!
  • 如果您需要更具体的解决方案,您应该发布原始数据文件的 sn-p。
  • 如果您关心性能,为什么您认为多次打开和访问文件会有帮助
【解决方案2】:

我尝试了几种不同的方法来使用 LINQ 执行此操作,但没有任何方法允许我对文件进行单次扫描。对于您所说的这种情况,我将下降到 Enumerable 级别并像这样使用 GetEnumerator:

public IEnumerable<LogData> GetLogData(string filename)
{
    var line1Regex = @"Line\s(\d+):\sGuid=([0123456789abcdefg]{8}-[0123456789abcdefg]{4}-[0123456789abcdefg]{4}-[0123456789abcdefg]{4}-[0123456789abcdefg]{12})\sname=\s(\w*)";
    int detailLines = 4;

    var lines = File.ReadAllLines(filename).GetEnumerator();
    while (lines.MoveNext())
    {
        var line = (string)lines.Current;
        var match = Regex.Match(line, line1Regex);
        if (!match.Success)
             continue;

        var details = new string[detailLines];
        for (int i = 0; i < detailLines && lines.MoveNext(); i++)
        {
            details[i] = (string)lines.Current;
        }

        yield return new LogData
        {
            Id = new Guid(match.Groups[2].Value),
            Name = match.Groups[3].Value,
            LineNumber = int.Parse(match.Groups[1].Value),
            Details = details
        };
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-01
    相关资源
    最近更新 更多