您的位置:首页 > 其它

统计一个大文本行数的几种方法以及效率统计(一)

2011-01-21 14:20 260 查看
最近在和一个朋友的交流中,遇到这么一个问题,如何能较快对一个较大的文本文件(1G或更大)的文本行数进行统计。如果不考虑效率,要统计一个文本的行数其实一点也不难,但是如果需要在较快的时间内做完,恐怕就得考虑实现方法了。

为此,自己尝试了几种方法,在这里把这几种方法拿出来和大家讨论一下。

首先是生成测试数据的代码:

const int COL_NUM = 30;
const int LINE_NUM = 10000000;
const string FILE_NAME = @"d:\test.csv";

/// <summary>
/// 创建一个一千万行的文本文件,大小约为900M。
/// </summary>
static void CreateTestCSVFile()
{
string rowValue = string.Join(string.Empty,
Enumerable.Range(1, COL_NUM).Select(i => i.ToString("00") + ","));

using (StreamWriter sw = new StreamWriter(FILE_NAME, false, Encoding.ASCII))
{
for (int i = 0; i < LINE_NUM; i++)
{
sw.WriteLine(rowValue);
}

}
}

.NET4.0 + StreamReader + ReadLine()

原理很简单,使用StreamReader的ReadLine方法,每执行一次,行数加一。代码如下:

/// <summary>
/// StreamReader + ReadLine()
/// </summary>
static void CalculateLine_ReadLine()
{
long lineCount = 0;
using (StreamReader sr = new StreamReader(FILE_NAME, false))
{
while (!sr.EndOfStream)
{
sr.ReadLine();
lineCount++;
}
}
Console.WriteLine("line count: {0}", lineCount);
}

测试结果如下:





对于以上这种方法,平均每次执行时间为55s左右,执行效率明显不尽如人意。

如果我们同样采用流,不过使用分块的方式,将文件内容一块一块读进内存,在解析每块内容的行数,最后相加。这样做的效率如何呢?

.NET4.0 + StreamReader + ReadBlock()

/// <summary>
/// StreamReader + ReadBlock()
/// </summary>
static void CalculateLine_ReadBlock(int oneBlockSize)
{

long lineCount = 0;
char[] oneBlock = new char[oneBlockSize];
using (StreamReader sr = new StreamReader(FILE_NAME, false))
{
long streamLen = sr.BaseStream.Length;
while (!sr.EndOfStream)
{
long leftLength = streamLen - sr.BaseStream.Position - 1;
if (leftLength >= oneBlockSize)
{
sr.ReadBlock(oneBlock, 0, oneBlock.Length);
lineCount += oneBlock.Count(c => c == '\r');
}
else
{
lineCount += sr.ReadToEnd().Count(c => c == '\r');
}
}
}

Console.WriteLine("line count: {0}", lineCount);
}

static void Main(string[] args)
{

int[] oneBlockArray = new[] { 1, 10, 20, 50, };
foreach (int oneBlockSize in oneBlockArray)
{

CodeTimerF2.CodeTimer.Time(string.Format("StreamReader + ReadBolck() [Block Size: {0}MB]", oneBlockSize),
1, () => CalculateLine_ReadBlock(oneBlockSize * 1024 * 1024));
}

Console.ReadKey();
}

运行结果如图:



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐