C# C Streamreader-仅在{CR}{LF}上中断
在执行复杂的SSIS插入包之前,我试图计算文本文件中要与控制文件进行比较的行数 目前,我正在使用StreamReader,它正在断开一行,并在新行中嵌入一个{LF},而SSI正在正确使用{CR}{LF},因此计数没有累计 有人知道这样做的另一种方法吗?我可以只根据{CR}{LF}换行来计算文件中的行数C# C Streamreader-仅在{CR}{LF}上中断,c#,.net,text-files,streamreader,flat-file,C#,.net,Text Files,Streamreader,Flat File,在执行复杂的SSIS插入包之前,我试图计算文本文件中要与控制文件进行比较的行数 目前,我正在使用StreamReader,它正在断开一行,并在新行中嵌入一个{LF},而SSI正在正确使用{CR}{LF},因此计数没有累计 有人知道这样做的另一种方法吗?我可以只根据{CR}{LF}换行来计算文件中的行数 提前感谢{CR}{LF}是需要的。真的说不出哪个是对的 因为ReadLine从行尾剥离,所以您不知道 使用并查找13,然后是10 它返回Int{CR}{LF}是所需的。真的说不出哪个是对的 因为R
提前感谢{CR}{LF}是需要的。真的说不出哪个是对的 因为ReadLine从行尾剥离,所以您不知道 使用并查找13,然后是10
它返回Int{CR}{LF}是所需的。真的说不出哪个是对的 因为ReadLine从行尾剥离,所以您不知道 使用并查找13,然后是10
它返回Int这里有一个非常懒惰的方法。。。这将把整个文件读入内存
var cnt = File.ReadAllText("yourfile.txt")
.Split(new[] { "\r\n" }, StringSplitOptions.None)
.Length;
这是一个相当懒惰的方法。。。这将把整个文件读入内存
var cnt = File.ReadAllText("yourfile.txt")
.Split(new[] { "\r\n" }, StringSplitOptions.None)
.Length;
迭代文件并计算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));
实际上,它是字符串任务中的查找子字符串。可以使用更通用的算法。迭代文件并计算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));
实际上,它是字符串任务中的查找子字符串。可以使用更通用的算法。这里有一个扩展方法,它只读取带有行分隔符{Cr}{Lf}的行,而不读取{Lf}。你可以数一数
var count= new StreamReader(@"D:\Test.txt").ReadLinesCrLf().Count()
但也可以将其用于读取文件,有时会很有用,因为正常的StreamReader.ReadLine在{Cr}{Lf}和{Lf}上都会中断。可用于任何文本阅读器和works流媒体文件大小不是问题
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();
}
这里是一个扩展方法,它只读取带有行分隔符{Cr}{Lf}的行,而不读取{Lf}。你可以数一数
var count= new StreamReader(@"D:\Test.txt").ReadLinesCrLf().Count()
但也可以将其用于读取文件,有时会很有用,因为正常的StreamReader.ReadLine在{Cr}{Lf}和{Lf}上都会中断。可用于任何文本阅读器和works流媒体文件大小不是问题
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();
}
你可以自己读取文件,然后按照自己的意愿进行拆分;只要读取字节,当您遇到一个{CR}{LF}时,就开始一行新的代码。^-这就是StreamReader在封面下的工作方式。它在CR,LF和CRLF上分开也许这有帮助。。快速自定义流读取器也可以解决其他断行问题。请参阅post@Clint:Reading bytes不是一件特别安全的事情,除非您确定文件编码是单字节字符集。事实上,如果文件是16位Unicode,则CR/LF对以4个字节编码:0x00、0x0D、0x00、0x0A。现在,如果您使用StreamReader以文本形式打开它并读取字符。你可以自己读取文件,然后按照自己的意愿进行拆分;只要读取字节,当您遇到一个{CR}{LF}时,就开始一行新的代码。^-这就是StreamReader在封面下的工作方式。它在CR,LF和CRLF上分开也许这有帮助。。快速自定义流读取器也可以解决其他断行问题。请参阅post@Clint:Reading bytes不是一件特别安全的事情,除非您确定文件编码是单字节字符集。事实上,如果文件是16位Unicode,则CR/LF对以4个字节编码:0x00、0x0D、0x00、0x0A。现在,如果您使用StreamReader以文本形式打开它并读取字符。由于大小的原因,一次读取整个文件不是一个选项,但对于较小的文件来说是一个不错的解决方案。由于大小的原因,一次读取整个文件不是一个选项,但是对于较小的文件来说是一个不错的解决方案。希望您不要遇到一个Unicode文件,其中一个字符的最后一个字节等于CR,而下一个字符的第一个字节是LF。您确实应该在回答中注意到,此解决方案不能保证适用于任何Unicode编码。@JimMischel感谢您指出这一点。原始答案在任何多字节编码上都会失败。修复了它。希望您不会遇到一个Unicode文件,其中一个字符的最后一个字节等于CR,而下一个字符的第一个字节等于LF。您确实应该在回答中注意到,此解决方案不能保证适用于任何Unicode编码。@JimMischel感谢您指出这一点。原始答案在任何多字节编码上都会失败。修好了。