0

嘿伙计们,我在从正在读入程序的 txt 文件中跳过一些不必要的行时遇到了一些麻烦。数据格式如下:

Line 1
Line 2
Line 3
Line 4

Line 5
Line 6
Line 7
Line 8

我想阅读第 1 行,修剪第 3、4 行和空白,然后阅读第 5 行,修剪第 7 和 8 行。我在本网站上阅读了与此类似的内容,但是,该特殊情况跳过了前 5文本文件的行。这是我到目前为止所尝试的:

         string TextLine;


        System.IO.StreamReader file =
           new System.IO.StreamReader("C://log.txt");
        while ((TextLine = file.ReadLine()) != null)
        {

            foreach (var i in Enumerable.Range(2, 3)) file.ReadLine();
            Console.WriteLine(TextLine);


        }

正如你们所看到的,对于范围,我已将开始指定为第 2 行,然后跳过 3 行,其中包括空格。但是, Enumerable.Range 的第一个参数似乎并不重要。我可以输入一个 0,它会产生相同的结果。正如我现在所拥有的那样,程序从第一行开始修剪,直到 .Range 函数的第二个参数中指定的数字。有谁知道解决这个问题的方法?谢谢

4

6 回答 6

3

为什么不将所有行读入一个数组,然后只索引你想要的行

var lines = File.ReadAllLines("C://log.txt");
Console.WriteLine(lines[0]);
Console.WriteLine(lines[5]);

如果它是一个具有一致重复部分的非常大的文件,您可以创建一个读取方法并执行以下操作:

while (!file.EndOfStream)
{
    yield return file.ReadLine();
    yield return file.ReadLine();
    file.ReadLine();
    file.ReadLine();
    file.ReadLine();
}

或类似您需要的任何块格式。

于 2012-04-16T15:30:51.900 回答
2

当然范围无关紧要......你正在做的是在每次while循环迭代中一次跳过2行 - 2-3对文件阅读器指针没有影响。我建议您只需有一个计数器告诉您您在哪一行,如果行号是您想跳过的行号之一,则跳过,例如

int currentLine = 1;
while ((TextLine = file.ReadLine()) != null)
{           
    if ( LineEnabled( currentLine )){
        Console.WriteLine(TextLine);
    }

    currentLine++;
}

 private boolean LineEnabled( int lineNumber )
 {
     if ( lineNumber == 2 || lineNumber == 3 || lineNumber == 4 ){ return false; }
     return true;
 }
于 2012-04-16T15:27:57.740 回答
2

我认为您不想在两个地方阅读该行(一个在循环中,然后又在循环内)。我会采取这种方法:

while ((TextLine = file.ReadLine()) != null)
{
    if (string.IsNullOrWhitespace(TextLine)) // Or any other conditions
        continue;

    Console.WriteLine(TextLine);
} 
于 2012-04-16T15:31:21.793 回答
2

这是应 OP 的要求在此处提供的解决方案的扩展版本。

public static IEnumerable<string> getMeaningfulLines(string filename)
{
  System.IO.StreamReader file =
    new System.IO.StreamReader(filename);
    while (!file.EndOfStream)
    {
      //keep two lines that we care about
      yield return file.ReadLine();
      yield return file.ReadLine();
      //discard three lines that we don't need
      file.ReadLine();
      file.ReadLine();
      file.ReadLine();
    }
}

public static void Main()
{
  foreach(string line in getMeaningfulLines(@"C:/log.txt"))
  {
    //or do whatever else you want with the "meaningful" lines.
    Console.WriteLine(line);
  }
}

这是另一个版本,如果输入文件突然结束,它会变得不那么脆弱。

//Just get all lines from a file as an IEnumerable; handy helper method in general.
public static IEnumerable<string> GetAllLines(string filename)
{
  System.IO.StreamReader file =
    new System.IO.StreamReader(filename);
  while (!file.EndOfStream)
  {
    yield return file.ReadLine();
  }
}

public static IEnumerable<string> getMeaningfulLines2(string filename)
{
  int counter = 0;
  //This will yield when counter is 0 or 1, and not when it's 2, 3, or 4.
  //The result is yield two, skip 3, repeat.
  foreach(string line in GetAllLines(filename))
  {
    if(counter < 2)
      yield return line;

    //add one to the counter and have it wrap, 
    //so it is always between 0 and 4 (inclusive).
    counter = (counter + 1) % 5;
  }
}
于 2012-04-16T19:15:34.773 回答
0

状态的文档Enumerable.Range

public static IEnumerable<int> Range(
int start,
int count
)

Parameters

start
 Type: System.Int32
 The value of the first integer in the sequence.

count
 Type: System.Int32
 The number of sequential integers to generate.

所以改变第一个参数不会改变你程序的逻辑。

但是,这是一种奇怪的方法。for循环会更简单、更容易理解并且效率更高。

此外,您的代码当前读取第一行,跳过三行,然后输出第一行,然后重复。

于 2012-04-16T15:28:52.093 回答
0

你有没有尝试过这样的事情?

using (var file = new StreamReader("C://log.txt"))
{
    var lineCt = 0;
    while (var line = file.ReadLine())
    {
        lineCt++;

        //logic for lines to keep
        if (lineCt == 1 || lineCt == 5)
        {
            Console.WriteLine(line);
        }
    }
}

尽管除非这是一个非常固定格式的输入文件,否则我会找到一种不同的方法来确定如何处理每一行而不是固定的行号。

于 2012-04-16T15:29:51.663 回答