繁体   English   中英

获取文本文件中的行数估计

[英]Get Estimate of Line Count in a text file

我想估计csv / text文件中的行数,以便我可以将该数字用于进度条。 该文件可能非常大,因此为此目的获取确切的行数将花费太长时间。

我想出的是下面的内容(读入文件的一部分并计算行数并使用文件大小来估计总行数):

    public static int GetLineCountEstimate(string file)
    {
        double count = 0;
        using (var fs = new FileStream(file, FileMode.Open, FileAccess.Read))
        {
            long byteCount = fs.Length;
            int maxByteCount = 524288;
            if (byteCount > maxByteCount)
            {
                var buf = new byte[maxByteCount];
                fs.Read(buf, 0, maxByteCount);
                string s = System.Text.Encoding.UTF8.GetString(buf, 0, buf.Length);
                count = s.Split('\n').Length * byteCount / maxByteCount;
            }
            else
            {
                var buf = new byte[byteCount];
                fs.Read(buf, 0, (int)byteCount);
                string s = System.Text.Encoding.UTF8.GetString(buf, 0, buf.Length);
                count = s.Split('\n').Length;
            }
        }
        return Convert.ToInt32(count);
    }

这似乎工作正常,但我有一些担忧:

1)我想将我的参数简单地作为Stream(而不是文件名),因为我也可能正在从剪贴板(MemoryStream)中读取。 但是,Stream似乎无法一次读取n个字节到缓冲区或者以字节为单位获取Stream的总长度,就像FileStream一样。 Stream是MemoryStream和FileStream的父类。

2)我不想假设UTF8这样的编码

3)我不想假设行尾字符(它应该适用于CR,CRLF和LF)

我将不胜感激任何使这个功能更强大的帮助。

以下是我提出的用于估算行数的更强大的解决方案。

public static int EstimateLineCount(string file)
{
    using (var fs = new FileStream(file, FileMode.Open, FileAccess.Read))
    {
        return EstimateLineCount(fs);
    }
}

public static int EstimateLineCount(Stream s)
{
    //if file is larger than 10MB estimate the line count, otherwise get the exact line count
    const int maxBytes = 10485760; //10MB = 1024*1024*10 bytes

    s.Position = 0;
    using (var sr = new StreamReader(s, Encoding.UTF8))
    {
        int lineCount = 0;
        if (s.Length > maxBytes)
        {
            while (s.Position < maxBytes && sr.ReadLine() != null)
                lineCount++;

            return Convert.ToInt32((double)lineCount * s.Length / s.Position);
        }

        while (sr.ReadLine() != null)
            lineCount++;
        return lineCount;
    }
}
var lineCount = File.ReadLines(@"C:\file.txt").Count();

其他方式:

var lineCount = 0;
using (var reader = File.OpenText(@"C:\file.txt"))
{
    while (reader.ReadLine() != null)
    {
        lineCount++;
    }
}

你在作弊! 你问了不止一个问题......无论如何我会尽力帮助你:P

  1. 不,您不能使用Stream,但您可以使用StreamReader。 这应该提供您所需的灵活性。

  2. 测试编码,因为我推断你将使用各种各样的。 但请记住,通常很难满足所有场景,因此首先选择一些重要的场景,然后再扩展您的程序。

  3. 不要 - 让我告诉你如何:

首先,考虑你的来源。 无论是文件还是内存流,您都应该了解它的大小。 我已经完成了文件位,因为我很懒,而且很容易,所以你必须自己弄清楚内存流位。 我所做的更简单但更不准确:读取文件的第一行,并将其用作文件大小的百分比。 注意我将字符串的长度乘以2,因为它是delta,换句话说,是字符串中每个额外字符使用的额外字节数。 显然这不是很准确,所以你可以将它扩展到x行,只要记住你也必须改变公式。

static void Main(string[] args)
    {
        FileInfo fileInfo = new FileInfo((@"C:\Muckabout\StringCounter\test.txt"));
        using (var stream = new StreamReader(fileInfo.FullName))
        {
            var firstLine = stream.ReadLine(); // Read the first line.
            Console.WriteLine("First line read. This is roughly " + (firstLine.Length * 2.0) / fileInfo.Length * 100 + " per cent of the file.");
        }
        Console.ReadKey();
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM