views:

236

answers:

4

Hello,

For a project that I am doing, one of the things that I must do is delete the first X lines of a plaintext file. I'm saying X because I will need to do this routine multiple times and each time, the lines to delete will be different, but they will always start from the beginning, delete the first X and then output the results to the same file.

I am thinking about doing something like this, which I pieced together from other tutorials and examples that I read:

String line = null;

String tempFile = Path.GetTempFileName();
String filePath = openFileDialog.FileName;

int line_number = 0;
int lines_to_delete = 25;

using (StreamReader reader = new StreamReader(originalFile)) {
    using (StreamWriter writer = new StreamWriter(tempFile)) {
        while ((line = reader.ReadLine()) != null) {
            line_number++;

            if (line_number <= lines_to_delete)
                continue;

            writer.WriteLine(line);
        }
    }
}

if (File.Exists(tempFile)) {
    File.Delete(originalFile);
    File.Move(tempFile, originalFile);
}

But I don't know if this would work because of small stuff like line numbers starting at line 0 or whatnot... also, I don't know if it is good code in terms of efficiency and form.

Thanks a bunch.

+3  A: 

It's OK, and doesn't look it would have the off-by-one problems you fear. However a leaner approach would be afforded by two separate loops -- one to just count the first X lines from the input file (and do nothing else), a separate one to just copy the other lines from input to output. I.e., instead of your single while loop, have...:

    while ((line = reader.ReadLine()) != null) {
        line_number++;

        if (line_number > lines_to_delete)
            break;
    }

    while ((line = reader.ReadLine()) != null) {
        writer.WriteLine(line);
    }
Alex Martelli
This works because when I do reader.ReadLine() again, it resumes reading from where it left off, right?If I wanted to make another reader called "reader" (as this would be in a larger loop that would repeat this process multiple times) I would just have to close "reader" and then when I made another one, it would start back from the beginning of the file, correct?
Unk
@Unk, yep, to both questions in this comment.
Alex Martelli
Thanks a bunch!
Unk
@Unk, you're welcome!
Alex Martelli
A: 

You could read the file into an array of lines, ignore the first few elements, and write the rest back.

The downside to this approach is that it will consume the size of the file in memory. Your approach (although pretty unreadable, no offence) doesn't have this memory problem. Although if the files are not too large, there shouldn't be a reason to worry about memory usage.

Example:

string[] lines = System.IO.File.ReadAllLines("YourFile.txt").Skip(10).ToArray();
System.IO.File.WriteAllLines("OutFile.txt", lines);
Charlie Somerville
Yeah, the main problem is that the file is EXTREMELY large and the computer on which the program would run isn't exactly top-notch. I am already using a bunch of arrays for stuff so that's why I went with my approach to doing it; reading it and writing it on the spot.Thanks for your help, anyways.
Unk
Oops, my bad, forget the ToArray()
Charlie Somerville
+3  A: 

I like it short...

File.WriteAllLines(
    fileName,
    File.ReadAllLines(fileName).Skip(numberLinesToSkip).ToArray());
Daniel Brückner
Nice clean solution. Will cause problems though if the source file is too big since it reads the entire file into memory.
LukeH
Yeah, It's really clean, but as I mentioned in Charlie's post, the file is extremely large and this application will not be run on a powerful machine...Thanks though; I didn't know about all those methods that you used and I learned some new stuff!
Unk
A: 

I like your approach, I see nothing wrong with it. If you know for certain they are small files then the other suggestions may be a little less code if that matters to you.

A slightly less verbose version of what you already have:

using (StreamReader reader = new StreamReader(originalFile))
using (StreamWriter writer = new StreamWriter(tempFile))
{
 while(lines_to_delete-- > 0)
  reader.ReadLine();
 while ((line = reader.ReadLine()) != null)
  writer.WriteLine(line);
}
csharptest.net
Thanks for your contribution!
Unk