简体   繁体   中英

is there any way to ignore reading in certain lines in a text file?

I'm trying to read in a text file in ac# application, but I don't want to read the first two lines, or the last line. There's 8 lines in the file, so effectivly I just want to read in lines, 3, 4, 5, 6 and 7. Is there any way to do this?

example file

USE [Shelley's Other Database]
CREATE TABLE db.exmpcustomers(
fName varchar(100) NULL,
lName varchar(100) NULL,
dateOfBirth date NULL,
houseNumber int NULL,
streetName varchar(100) NULL
) ON [PRIMARY]

EDIT

Okay, so, I've implemented Callum Rogers answer into my code and for some reason it works with my edited text file (I created a text file with the lines I didn't want to use omitted) and it does exactly what it should, but whenever I try it with the original text file (above) it throws an exception. I display this information in a DataGrid and I think that's where the exception is being thrown.

Any ideas?

The Answer by Rogers is good, I am just providing another way of doing this. Try this,

List<string> list = new List<string>();
using (StreamReader reader = new StreamReader(FilePath))
{
    string text = "";
    while ((text = reader.ReadLine()) != null)
    {
        list.Add(text);
    }
    list.RemoveAt(0);
    list.RemoveAt(0);
 }

Hope this helps

Why not just use File.ReadAllLines() and then remove the first 2 lines and the last line? With such a small file speed differences will not be noticeable.

string[] allLines = File.ReadAllLines("file.ext");
string[] linesWanted = new string[allLines.Length-3];
Array.Copy(allLines, 2, linesWanted, 0, allLines.Length-3);

Why do you want to ignore exactly the first two and the last line?

Depending on what your file looks like you might want to analyze the line, eg look at the first character whether it is a comment sign, or ignore everything until you find the first empty line, etc.

Sometimes, hardcoding "magic" numbers isn't such a good idea. What if the file format needs to be changed to contain 3 header lines?

As the other answers demonstrate: Nothing keeps you from doing what you ever want with a line you have read, so of course, you can ignore it, too.

Edit, now that you've provided an example of your file: For your case I'd definitely not use the hardcoded numbers approach. What if some day the SQL statement should contain another field, or if it appears on one instead of 8 lines?

My suggestion: Read in the whole string at once, then analyze it. Safest way would be to use a grammar , but if you presume the SQL statement is never going to be more complicated, you can use a regular expression (still much better than using line numbers etc.):

string content = File.ReadAllText(filename);
Regex r = new Regex(@"CREATE TABLE [^\(]+\((.*)\) ON");
string whatYouWant = r.Match(content).Groups[0].Value;

If you have a TextReader object wrapping the filestream you could just call ReadLine() two times.

StreamReader inherits from TextReader, which is abstract.

Non-fool proof example:

using (var fs = new FileStream("blah", FileMode.Open))
using (var reader = new StreamReader(fs))
{
    reader.ReadLine();
    reader.ReadLine();

    // Do stuff.
}

You can do this:

var valid = new int[] { 3, 4, 5, 6, 7 };
var lines = File.ReadAllLines("file.txt").
    Where((line, index) => valid.Contains(index + 1));

Or the opposite:

var invalid = new int[] { 1, 2, 8 };
var lines = File.ReadAllLines("file.txt").
    Where((line, index) => !invalid.Contains(index + 1));

If you're looking for a general way to remove the last and the first 2, you can use this:

var allLines = File.ReadAllLines("file.txt");
var lines = allLines
  .Take(allLines.Length - 1)
  .Skip(2);

But from your example it seems that you're better off looking for the string pattern that you want to read from the file. Try using regexes.

string filepath = @"C:\whatever.txt";
using (StreamReader rdr = new StreamReader(filepath))
{
    rdr.ReadLine();  // ignore 1st line
    rdr.ReadLine();  // ignore 2nd line
    string fileContents = "";
    while (true)
    {
        string line = rdr.ReadLine();
        if (rdr.EndOfStream)
            break;  // finish without processing last line
        fileContents += line + @"\r\n";
    }
    Console.WriteLine(fileContents);
}

How about a general solution?

To me, the first step is to enumerate over the lines of a file (already provided by ReadAllLines , but that has a performance cost due to populating an entire string[] array; there's also ReadLines , but that's only available as of .NET 4.0).

Implementing this is pretty trivial:

public static IEnumerable<string> EnumerateLines(this FileInfo file)
{
    using (var reader = file.OpenText())
    {
        while (!reader.EndOfStream)
        {
            yield return reader.ReadLine();
        }
    }
}

The next step is to simply skip the first two lines of this enumerable sequence. This is straightforward using the Skip extension method.

The last step is to ignore the last line of the enumerable sequence. Here's one way you could implement this:

public static IEnumerable<T> IgnoreLast<T>(this IEnumerable<T> source, int ignoreCount)
{
    if (ignoreCount < 0)
    {
        throw new ArgumentOutOfRangeException("ignoreCount");
    }

    var buffer = new Queue<T>();
    foreach (T value in source)
    {
        if (buffer.Count < ignoreCount)
        {
            buffer.Enqueue(value);
            continue;
        }

        T buffered = buffer.Dequeue();

        buffer.Enqueue(value);

        yield return buffered;
    }
}

OK, then. Putting it all together, we have:

var file = new FileInfo(@"path\to\file.txt");
var lines = file.EnumerateLines().Skip(2).IgnoreLast(1);

Test input (contents of file):

This is line number 1.
This is line number 2.
This is line number 3.
This is line number 4.
This is line number 5.
This is line number 6.
This is line number 7.
This is line number 8.
This is line number 9.
This is line number 10.

Output (of Skip(2).IgnoreLast(1) ):

This is line number 3.
This is line number 4.
This is line number 5.
This is line number 6.
This is line number 7.
This is line number 8.
This is line number 9.

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