0

I'm using StreamWriter to write into file, but I need the index of line I'm writing to.

int i;
using (StreamWriter s = new StreamWriter("myfilename",true) {   
    i= s.Index(); //or something that works.
    s.WriteLine("text");    
}

My only idea is to read the whole file and count the lines. Any better solution?

rene
  • 41,474
  • 78
  • 114
  • 152
Tejföl
  • 5
  • 3
  • @rene: the duplicate seems to be about streamreaders, not streamwriters and it isn't obvious how the answers on that question would apply here... – Chris Apr 07 '18 at 20:23
  • @Chris hmm, that is true and I can't find another duplicate. Reopening and editing – rene Apr 07 '18 at 20:29
  • Why can't you do `i++;` instead of `i = s.Index();`? Or do you also write \r\n in your text? – rene Apr 07 '18 at 20:32
  • @rene: note the writer is appending so presumably the op needs to know how manyblines already exist before they can do their own tracking. – Chris Apr 07 '18 at 20:45
  • 2
    That is kind of dead-end then. They still need the StreamReader then or at least read what already is in the file. – rene Apr 07 '18 at 20:47
  • So you telling me that reading the file and counting its lines first, is the only way? – Tejföl Apr 07 '18 at 20:53
  • @Tejföl if you don't have that info stored anywhere else, yes. One option might be if all lines are the same length and your file is written in an encoding that uses a fixed number of bytes per char you can calculate how many lines there are by dividing filesize and linelenght. – rene Apr 07 '18 at 21:04

1 Answers1

1

The definition of a line

The definition of a line index and more specifically a line in a file is denoted by the \n character. Typically (and on Windows moreso) this can be preceded by the carriage return \r character too, but not required and not typically present on Linux or Mac.

Correct Solution

So what you are asking is for the line index at the current position basically means you are asking for the number of \n present before the current position in the file you are writing to, which seems to be the end (appending to the file), so you can think of it as how many lines are in the file.

You can read the stream and count these, with consideration for your machines RAM and to not just read in the entire file into memory. So this would be safe to use on very large files.

// File to read/write
var filePath = @"C:\Users\luke\Desktop\test.txt";

// Write a file with 3 lines
File.WriteAllLines(filePath, 
    new[] {
        "line 1",
        "line 2",
        "line 3",
    });

// Get newline character
byte newLine = (byte)'\n';

// Create read buffer
var buffer = new char[1024];

// Keep track of amount of data read
var read = 0;

// Keep track of the number of lines
var numberOfLines = 0;

// Read the file
using (var streamReader = new StreamReader(filePath))
{
    do
    {
        // Read the next chunk
        read = streamReader.ReadBlock(buffer, 0, buffer.Length);

        // If no data read...
        if (read == 0)
            // We are done
            break;

        // We read some data, so go through each character... 
        for (var i = 0; i < read; i++)
            // If the character is \n
            if (buffer[i] == newLine)
                // We found a line
                numberOfLines++;
    }
    while (read > 0);
}

The lazy solution

If your files are not that large (large being dependant on your intended machine/device RAM and program as a whole) and you want to just read the entire file into memory (so into your programs RAM) you can do a one liner:

var numberOfLines = File.ReadAllLines(filePath).Length;
angelsix
  • 392
  • 1
  • 7