zoukankan      html  css  js  c++  java
  • 统计一个大文本行数的几种方法以及效率统计(一)

    最近在和一个朋友的交流中,遇到这么一个问题,如何能较快对一个较大的文本文件(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);
            }

    测试结果如下:

    StreamReader ReadLine()

    对于以上这种方法,平均每次执行时间为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();
            }

    运行结果如图:

    StreamReader ReadBlock()

  • 相关阅读:
    10 个雷人的注释,就怕你不敢用!
    Java 14 之模式匹配,非常赞的一个新特性!
    poj 3661 Running(区间dp)
    LightOJ
    hdu 5540 Secrete Master Plan(水)
    hdu 5584 LCM Walk(数学推导公式,规律)
    hdu 5583 Kingdom of Black and White(模拟,技巧)
    hdu 5578 Friendship of Frog(multiset的应用)
    hdu 5586 Sum(dp+技巧)
    hdu 5585 Numbers
  • 原文地址:https://www.cnblogs.com/quark/p/1941109.html
Copyright © 2011-2022 走看看