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等值,而不浪费不必要的资源,并以相对及时的方式完成?

ReadLine() vs Read()有效获取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()。这样你就不必担心字符串是如何结束的。

ie

 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()一样有效。我真的很担心这不会有那么好的效果。看来我错了。