ReadLine()vs Read()有效获取CR和LF?

时间:2011-09-01 21:52:41

标签: c# visual-studio-2010 io readline

我正在开发一个C#程序,用于在使用SSIS包导入之前确定具有100,000多行的多个大文本文件中每行的行长度。我还将检查每一行上的其他值,以验证它们是否正确,以便使用SSIS将它们导入我的数据库。

例如,我期望行长度为3000个字符,然后CR为3001,LF为3002,总共3002个字符。

当使用ReadLine()时,它会读取CR或LF作为行尾,这样我就无法检查CR或LF字符。我只是在3000处检查线的长度以确定长度是否正确。我刚刚遇到一个问题,即文件在位置3001处有一个LF但是缺少CR。所以ReadLine()说它是3000 char女巫是正确的但它会在我的SSIS包中失败,因为它缺少一个CR。

我已经确认Read()将一次到达每个char 1,我可以确定每行是否有CR和LF但这似乎相当无效,当我遇到的某些文件有超过5,000,000+行时这似乎非常低效。我还需要将每个char添加到字符串中或使用ReadBlock()并将char数组转换为字符串,以便我可以检查该行中的其他值。

有没有人有一个有效的方法来检查CR和LF以及给定线路上的其他值的线路,而不会浪费不必要的资源并以相对及时的方式完成。

5 个答案:

答案 0 :(得分:4)

  

已经验证Read()将一次到达每个char 1,我可以确定每行是否有CR和LF但这似乎相当无效

想一想。你认为ReadLine()有一根魔杖而且不必阅读每一个字符吗?

只需创建自己的ReadMyLine()。有些东西必须读取字符,无论这是你的代码还是lib。 I / O将由Stream和Windows缓冲。

答案 1 :(得分:1)

我可能在这里遗漏了一些东西,但是如果每行中的数据总是精确到3000个字符(不包括CR和LF)?

为什么不使用string.Substring()读取每一行,然后仅使用前3000个字符。这样您就不必担心字符串的终止方式。

 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
          }
     }

答案 2 :(得分:1)

你可以使用an override of StreamReader.Read OR an override of TextReader.Read接受3个参数 - 字符串缓冲区(在你的情况下是一个3002字符数组),startint索引(每次递增索引时你都会在循环中处理它3002),要读取的字符数(3002)。从读缓冲区,您可以检查CR和LF的条件评估的最后两个字符。

答案 3 :(得分:1)

我相信你会发现这个版本效率很高:

    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;
    }

我对此持乐观态度的原因是,根据the docs,如果底层缓冲区的大小与用于读取的缓冲区匹配,则效率会提高。警告:此代码尚未经过测试或定时。

答案 4 :(得分:0)

我想我终于找到了准确得到我想要的代码,想法?我遇到的主要问题是我无法保证我的线路长度会纠正。另一方面,@ 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()一样有效。我真的害怕这不会有效。看来我错了。