我正在尝试在执行复杂的SSIS插入包之前计算文本文件中的行数(以与控制文件进行比较)。
目前我正在使用一个StreamReader,它正在打破一条嵌入新行的{LF}行,而SSIS正在使用{CR} {LF}(正确),因此计数不合理。
有没有人知道另一种方法,我可以根据{CR} {LF}换行计算文件中的行数?
提前致谢
答案 0 :(得分:3)
遍历文件并计算CRLF的数量。
非常简单的实施:
public int CountLines(Stream stream, Encoding encoding)
{
int cur, prev = -1, lines = 0;
using (var sr = new StreamReader(stream, encoding, false, 4096, true))
{
while ((cur = sr.Read()) != -1)
{
if (prev == '\r' && cur == '\n')
lines++;
prev = cur;
}
}
//Empty stream will result in 0 lines, any content would result in at least one line
if (prev != -1)
lines++;
return lines;
}
使用示例:
using(var s = File.OpenRead(@"<your_file_path>"))
Console.WriteLine("Found {0} lines", CountLines(s, Encoding.Default));
实际上它是字符串任务中的查找子字符串。可以使用更通用的算法。
答案 1 :(得分:2)
答案 2 :(得分:2)
这是一种非常懒惰的方式......这会将整个文件读入内存。
var cnt = File.ReadAllText("yourfile.txt")
.Split(new[] { "\r\n" }, StringSplitOptions.None)
.Length;
答案 3 :(得分:0)
这是一种扩展方法,它仅使用行分隔符{Cr} {Lf}而不是{LF}读取行。您可以依靠它。
var count= new StreamReader(@"D:\Test.txt").ReadLinesCrLf().Count()
但是也可以使用它来读取文件,由于正常的StreamReader.ReadLine在{Cr} {Lf}和{LF}上都中断,因此有时很有用。可以在任何TextReader上使用,并且可以流式传输(文件大小不是问题)。
public static IEnumerable<string> ReadLinesCrLf(this TextReader reader, int bufferSize = 4096)
{
StringBuilder lineBuffer = null;
//read buffer
char[] buffer = new char[bufferSize];
int charsRead;
var previousIsLf = false;
while ((charsRead = reader.Read(buffer, 0, bufferSize)) != 0)
{
int bufferIndex = 0;
int writeIdx = 0;
do
{
var currentChar = buffer[bufferIndex];
switch (currentChar)
{
case '\n':
if (previousIsLf)
{
if (lineBuffer == null)
{
//return from current buffer writeIdx could be higher than 0 when multiple rows are in the buffer
yield return new string(buffer, writeIdx, bufferIndex - writeIdx - 1);
//shift write index to next character that will be read
writeIdx = bufferIndex + 1;
}
else
{
Debug.Assert(writeIdx == 0, $"Write index should be 0, when linebuffer != null");
lineBuffer.Append(buffer, writeIdx, bufferIndex - writeIdx);
Debug.Assert(lineBuffer.ToString().Last() == '\r',$"Last character in linebuffer should be a carriage return now");
lineBuffer.Length--;
//shift write index to next character that will be read
writeIdx = bufferIndex + 1;
yield return lineBuffer.ToString();
lineBuffer = null;
}
}
previousIsLf = false;
break;
case '\r':
previousIsLf = true;
break;
default:
previousIsLf = false;
break;
}
bufferIndex++;
} while (bufferIndex < charsRead);
if (writeIdx < bufferIndex)
{
if (lineBuffer == null) lineBuffer = new StringBuilder();
lineBuffer.Append(buffer, writeIdx, bufferIndex - writeIdx);
}
}
//return last row
if (lineBuffer != null && lineBuffer.Length > 0) yield return lineBuffer.ToString();
}