ReadLine() vs Read()有效获取CR和LF
本文关键字:CR LF 获取 Read vs ReadLine 有效 | 更新日期: 2023-09-27 18:07:32
我正在编写一个c#程序,在使用SSIS包导入之前,确定具有100,000行以上的多个大型文本文件中每行的行长。在使用SSIS将它们导入数据库之前,我还将检查每行上的其他值以验证它们是否正确。
例如,我期望行长为3000个字符,然后CR为3001,LF为3002,所以总体上总共有3002个字符。
当使用ReadLine()时,它读取CR或LF作为行尾,因此我不能检查CR或LF字符。我刚刚检查了线的长度在3000,以确定长度是否正确。我刚刚遇到了一个问题,文件在3001位置有一个LF,但缺少CR.所以ReadLine()说它是3000字符转换是正确的,但它会在我的SSIS包中失败,因为它缺少CR。
我已经验证了Read()将一次到达每个char 1,我可以确定每行是否有CR和LF,但这似乎相当低效,当我遇到的一些文件超过5,000,000行时,这似乎非常低效。然后,我还需要将每个字符添加到字符串中,或者使用ReadBlock()并将字符数组转换为字符串,以便我可以检查该行中的其他值。
有没有人有什么有效的方法来检查线路上的CR和LF等值,而不浪费不必要的资源,并以相对及时的方式完成?
已经验证了Read()将一次到达每个char 1,我可以确定每行是否有CR和LF,但这似乎相当无效
想想这个。你认为ReadLine()
有魔棒,不需要读取每个字符吗?
创建你自己的ReadMyLine()。必须有东西读取这些字符,这与你的代码或库无关。I/O将被流和Windows缓冲。
你可以使用重写StreamReader吗?读取或重写TextReader。Read接受3个参数-字符串缓冲区(在您的例子中是一个3002字符数组),开始索引(您将在每次将索引增加3002的循环中处理),要读取的字符数(3002)。从读缓冲区中,您可以检查CR和LF的条件求值的最后两个字符。
我相信你会发现这个版本是高效的:
static bool CheckFile(string filename)
{
const int BUFFER_SIZE = 3002;
var Reader = new StreamReader(filename, Encoding.ASCII, false, BUFFER_SIZE);
var buffer = new char[BUFFER_SIZE];
int offset = 0;
int bytesRead = 0;
while((bytesRead = Reader.Read(buffer, offset, BUFFER_SIZE)) > 0)
{
if(bytesRead != BUFFER_SIZE
|| buffer[BUFFER_SIZE - 2] != ''r'
|| buffer[BUFFER_SIZE - 1] != ''n')
{
//the file does not conform
return false;
}
offset += bytesRead;
}
return true;
}
我对此持乐观态度的原因是,根据文档,如果底层缓冲区的大小与用于读取的缓冲区匹配,则效率会提高。注意:此代码未经过测试或计时。
我可能在这里错过了一些东西,但是如果每行中的数据总是恰好3000个字符(不包括CR和LF)?
为什么不读取每行,然后只取前3000个字符,使用string.Substring()
。这样你就不必担心字符串是如何结束的。
using (StreamReader sr = new StreamReader("TestFile.txt"))
{
String line;
while ((line = sr.ReadLine()) != null)
{
// string data = line.subString(0,3000);
// edit, if data is sometimes < 3000 ....
string data = line.subString(0,line.length < 3000 ? line.length : 3000);
// do something with data
}
}
我想我终于弄清楚了代码,得到我想要的,想法?我遇到的主要问题是,我不能保证我的线长是正确的。否则,@Paul Keister提到的方法就会很有效,正如我所测试的那样。谢谢你的帮助!
int asciiValue = 0;
while (asciiValue != -1)
{
Boolean endOfRow = false;
Boolean endOfRowValid = true;
string currentLine = "";
while (endOfRow == false)
{
asciiValue = file.Read();
if (asciiValue == 10 || asciiValue == 13)
{
int asciiValueTemp = file.Peek();
if (asciiValue == 13 && asciiValueTemp == 10)
{
endOfRow = true;
asciiValue = file.Read();
}
else
{
endOfRowValid = false;
endOfRow = true;
}
}
else if (asciiValue != -1)
currentLine += char.ConvertFromUtf32(asciiValue);
else
endOfRow = true;
}
编辑:我忘了说这似乎和使用ReadLine()一样有效。我真的很担心这不会有那么好的效果。看来我错了。