获取文本文件中行数的估计值
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 的父 class。
2) 我不想假定编码如 UTF8
3) 我不想假定行尾字符(它应该适用于 CR、CRLF 和 LF)
如能帮助我提高此功能,我将不胜感激。
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
不,你不能使用 Stream,但你可以使用 StreamReader。这应该可以提供您需要的灵活性。
测试编码,因为我推断您将使用各种。但是请记住,通常很难满足所有场景的需求,因此请先选择一些重要场景,然后再扩展您的程序。
不要 - 让我告诉你怎么做:
首先,考虑你的来源。无论是文件还是内存流,您都应该知道它的大小。我已经完成了文件位,因为我很懒而且很容易,所以你必须自己弄清楚内存流位。我所做的要简单得多但不太准确:读取文件的第一行,并将其用作文件大小的百分比。请注意,我将字符串的长度乘以 2,因为这是增量,换句话说,字符串中每个额外字符使用的额外字节数。显然这不是很准确,因此您可以将其扩展到 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();
}
这是我想出的更强大的估计行数解决方案。
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;
}
}
我想估计 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 的父 class。
2) 我不想假定编码如 UTF8
3) 我不想假定行尾字符(它应该适用于 CR、CRLF 和 LF)
如能帮助我提高此功能,我将不胜感激。
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
不,你不能使用 Stream,但你可以使用 StreamReader。这应该可以提供您需要的灵活性。
测试编码,因为我推断您将使用各种。但是请记住,通常很难满足所有场景的需求,因此请先选择一些重要场景,然后再扩展您的程序。
不要 - 让我告诉你怎么做:
首先,考虑你的来源。无论是文件还是内存流,您都应该知道它的大小。我已经完成了文件位,因为我很懒而且很容易,所以你必须自己弄清楚内存流位。我所做的要简单得多但不太准确:读取文件的第一行,并将其用作文件大小的百分比。请注意,我将字符串的长度乘以 2,因为这是增量,换句话说,字符串中每个额外字符使用的额外字节数。显然这不是很准确,因此您可以将其扩展到 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();
}
这是我想出的更强大的估计行数解决方案。
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;
}
}