使用LINQ处理文本文件

3

文本文件格式

headerinfo = "abc"
**part1=001**
element1
element2....
...
element15
end_element
**part2=002**
element1
element2....
...
emelent15
end_element
......
end_header

我想选择从part1=001开始到但不包括part2=002的所有文本行。

目前为止,我的做法是:

var res = (from line in File.ReadAllLines(sExecPath + @"\" + sFileName)
           where line == "part1=001"
           select line).ToList();

我正在尝试在LINQ中使用between选项,但似乎没有返回任何结果。

var part1= (from prt in File.ReadAllLines(sExecPath + @"\" + sFileName)
            where prt.CompareTo("part1=001") >=0  
            && prt.CompareTo("part=002") >= 0
            select prt);
4个回答

8

我认为您正在寻找TakeWhile函数:

var linesInPartOne = File
       .ReadAllLines(sExecPath + @"\" + sFileName)
       .SkipWhile(line => !line.StartsWith("**part1="))
       // To skip to part 1 header line, uncomment the line below:
       // Skip(1)
       .TakeWhile(line => !line.StartsWith("**part2="));

为了将其推广到检索任何给定的编号部分,可以使用以下代码:
public static IEnumerable<String> ReadHeaderPart(String filePath, int part) {
    return File
        .ReadAllLines(filePath)
        .SkipWhile(line => !line.StartsWith("**part" + part + "="))
        // To skip to part 1 header line, uncomment the line below:
        // Skip(1)
       .TakeWhile(line => 
            !line.StartsWith("**part" + (part + 1) + "=" 
            && 
            !line.StartsWith("end_header")))
       .ToList();
 }

编辑:我在这个代码中使用了Skip(1)跳过了第1部分的标题,但是你似乎想保留这行代码,所以我已经将其删除了。


1
在这种特定情况下,您不应该使用SkipWhile跳过所有行到“part1”(仅为一行)吗? - Christoffer Lette
我的猜测是下一个问题会是“如何获取part2和part3之间的所有行”... :-) - Christoffer Lette
已编辑以避免可能性;-) - Chris Shain
Chris: 为什么不使用一个带有startPartendPart参数的方法 ReadFilePart,可以用于任何文件?;-) - Tim Schmelter
趁此机会,我还会让这个函数在早上为我冲咖啡 :-) - Chris Shain
显然Jeff已经喝了足够的咖啡 :) - Tim Schmelter

6
public static IEnumerable<string> GetLinesBetween(
    string path,
    string fromInclusive,
    string toExclusive)
{
    return File.ReadLines(path)
        .SkipWhile(line => line != fromInclusive)
        .TakeWhile(line => line != toExclusive);
}

var path = Path.Combine(sExecPath, sFileName); // don't combine paths like that
var result = GetLinesBetween(path, "part1=001", "part2=002").ToList();

1
最简单且直接的解决方案就像这样:
var lines = File.ReadAllLines(@"C:\Sample.txt").
             SkipWhile(line=>!line.Contains("part1")).
                   Skip(1).TakeWhile(line=>!line.Contains("part2"));

它实际上返回您想要的结果。 逻辑很简单:

  • SkipWhile 跳过行,直到遇到包含 "part1" 的行
  • Skip(1) 之后(因为它实际上是包含 "part1" 字符串的那一行)
  • 最后 Take 那些行,直到到达包含 "part2" 的行。

我尝试了这个,因为它只使用了几行代码 :-). 运行得非常好。 - user1181429

0

Linq 可能不是你最好的选择。只需尝试执行

var lines = File.ReadAllLines(filename);
List<string> linesICareABout = new List<string>();
for(int i = 0; !linesICareAbout[i].Contains("part2=002"); ++i)
{
 linesICareABout.Add(lines[i]);
}

然后,您可以对读取的行执行任何操作。

但是,如果您真的致力于使用Linq,请尝试TakeWhile

http://msdn.microsoft.com/en-us/library/bb534804.aspx


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接