Here are a few ways this can be accomplished quickly:
StreamReader:
using (var sr = new StreamReader(path))
{
while (!String.IsNullOrEmpty(sr.ReadLine()))
lineCount ++;
}
FileStream:
var lineBuffer = new byte[65536]; // 64Kb
using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read,
FileShare.Read, lineBuffer.Length))
{
int readBuffer = 0;
while ((readBuffer = fs.Read(lineBuffer, 0, lineBuffer.Length)) > 0)
{
for (int i = 0; i < readBuffer; i++)
{
if (lineBuffer[i] == 0xD) // Carriage return + line feed
lineCount++;
}
}
}
Multithreading:
Arguably the number of threads shouldn't affect the read speed, but real world benchmarking can sometimes prove otherwise. Try different buffer sizes and see if you get any gains at all with your setup. *This method contains a race condition. Use with caution.
var tasks = new Task[Environment.ProcessorCount]; // 1 per core
var fileLock = new ReaderWriterLockSlim();
int bufferSize = 65536; // 64Kb
using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read,
FileShare.Read, bufferSize, FileOptions.RandomAccess))
{
for (int i = 0; i < tasks.Length; i++)
{
tasks[i] = Task.Factory.StartNew(() =>
{
int readBuffer = 0;
var lineBuffer = new byte[bufferSize];
while ((fileLock.TryEnterReadLock(10) &&
(readBuffer = fs.Read(lineBuffer, 0, lineBuffer.Length)) > 0))
{
fileLock.ExitReadLock();
for (int n = 0; n < readBuffer; n++)
if (lineBuffer[n] == 0xD)
Interlocked.Increment(ref lineCount);
}
});
}
Task.WaitAll(tasks);
}