简体   繁体   中英

how to skip lines in txt file

Hey guys I've been having some trouble skipping some unnecessary lines from the txt file that I am reading into my program. The data has the following format:

Line 1
Line 2
Line 3
Line 4

Line 5
Line 6
Line 7
Line 8

I want to read line 1, trim lines 3, 4 and the white space and then read line 5, trim lines 7 and 8. I have read something similar to this here on this website, however, that particular case was skipping the first 5 lines of the text file. This is what I have tried so far:

         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);


        }

As you guys can see, for the range, I have specified the start as line 2 and then skip 3 lines, which includes the white space. However, that first parameter of Enumerable.Range does not seem to matter. I can put a 0 and it will yield the same results. As I have it right now, the program trims from the first line, until the number specified in the second parameter of the .Range function. Does anyone know of a way to get around this problem? Thanks

Why not read all the lines into an array and then just index the ones you want

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

If it's a really big file with consistent repeating sections you can create a read method and do:

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

or similar for whatever block format you need.

of course the range doesn't matter ... what you're doing is skipping 2 lines at a time inside every while loop iteration - the 2-3 has no effect on the file reader pointer. I would suggest you just have a counter telling you on which line you are and skip if the line number is one of those you'd like to skip, eg

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;
 }

I don't think you want to go about reading the line in two places (one in the loop and then again inside the loop). I would take this approach:

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

    Console.WriteLine(TextLine);
} 

Here's an expanded version of the solution provided here at the OP's request.

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);
  }
}

Here is another version that's going to be a little bit less fragile if the input file ends abruptly.

//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;
  }
}

The documentation for Enumerable.Range states:

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.

So changing the first parameter won't change the logic of your program.

However, this is an odd way to do this. A for loop would be much simpler, easier to understand and far more efficient.

Also, you're code currently reads the first line, skips three lines and then outputs the first line and then repeats.

Have you tried something like this?

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);
        }
    }
}

Although unless this is an extremely fixed format input file I'd find a different way to figure out what to do with each line rather than a fixed line number.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM