C# ReadLine()与Read()如何有效地获取CR和LF?

C# ReadLine()与Read()如何有效地获取CR和LF?,c#,visual-studio-2010,io,readline,C#,Visual Studio 2010,Io,Readline,在使用SSIS包导入之前,我正在开发一个C#程序,以确定多个包含100000多行的大型文本文件中每行的行长度。在使用SSIS将它们导入数据库之前,我还将检查每行上的其他值,以验证它们是否正确 例如,我希望行长度为3000个字符,然后CR为3001,LF为3002,因此总共为3002个字符 当使用ReadLine()时,它读取CR或LF as和行尾,因此我无法检查CR或LF字符。我刚刚检查了3000处的线路长度,以确定长度是否正确。我刚刚遇到一个问题,文件在3001位置有一个LF,但缺少CR。因此

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

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

当使用ReadLine()时,它读取CR或LF as和行尾,因此我无法检查CR或LF字符。我刚刚检查了3000处的线路长度,以确定长度是否正确。我刚刚遇到一个问题,文件在3001位置有一个LF,但缺少CR。因此ReadLine()说它是3000个字符,这是正确的,但它将在我的SSIS包中失败,因为它缺少CR

我已经验证了Read()将一次到达每个char 1,并且我可以确定每一行是否有CR和LF,但这似乎效率很低,当我遇到的一些文件有5000000+行时,这似乎效率很低。然后,我还需要将每个字符添加到字符串中,或者使用ReadBlock()将字符数组转换为字符串,以便检查行中的其他值


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

这里我可能遗漏了什么,但是如果每行中的数据总是正好3000个字符(不包括CR和LF)

为什么不使用
string.Substring()。这样,您就不必担心字符串是如何终止的

使用(StreamReader sr=newstreamreader(“TestFile.txt”))
{
弦线;
而((line=sr.ReadLine())!=null)
{
//字符串数据=行。子字符串(03000);
//编辑,如果数据有时小于3000。。。。
字符串数据=行子字符串(0,行长度<3000?行长度:3000);
//处理数据
}
}
您是否可以使用或接受3个参数-字符串缓冲区(在您的示例中为3002字符数组)、起始索引(每次将索引增加3002时,您将在循环中处理)、要读取的字符数(3002)。从读取缓冲区,您可以检查CR和LF条件计算的最后两个字符

我已经验证了Read()将一次到达每个字符1,并且我可以确定每行是否有一个CR和LF,但这似乎是徒劳的

想想这个。你认为
ReadLine()
有一根魔杖,不必读取每个字符吗


只需创建自己的ReadMyLine()。有些东西必须读取字符,不管这是您的代码还是库。I/O将由流和窗口缓冲

我相信您会发现这个版本非常有效:

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

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

我想我终于找到了我想要的代码,想法是什么?我遇到的主要问题是,我不能保证我的线路长度是正确的。另一方面,@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()一样有效。我真的很担心这不会起作用。看来我错了。

*注意:我尝试将Peek()与ReadLine()一起使用,它开始读取下一行,而不是读取CR和LF。我希望这是一个简单的解决办法。似乎一旦使用ReadLine(),它就会从StreamReader中删除CR和LF以进行澄清:虽然您正在检查有效数据,但导入是在原始原始文件上完成的,还是从已加载到C#程序中的数据中完成的?我猜是前者,但我想确定一下,它似乎效率低下?文件读取受到硬盘或网络速度的限制。您可以使用StreamReader.Read(char[],int,int)来读取一组字符。@JaredReisinger我正在对原始数据文件进行导入。我正在尝试对数据进行“预检查”,以防止导入过程失败,因为我收到了一个包含错误数据的文件。我以前使用过类似的方法。该行应始终为3000个字符,不包括CR和LF。然而,它并不总是,这就是为什么我需要检查长度,因为我从许多不同的来源获得的文件并不总是正确的长度。如果长度小于3000个字符,并且您将其作为子字符串,则它将失败并引发异常。@buzzz不要“认为”某个东西太慢,请测量。您的主要成本是I/O,而不是字符/字符串处理。我将使用
而(…){int ch=s.Read();…}
那么您可以使用
line.length<3000吗?line.length:3000
我可以,我目前正在尝试这种可能性。但是,在我已经尝试过的测试中,当与包含100000条记录的文件一起使用时,它的效率非常低。另一种方法是使用两个StreamReader—一个使用ReadLine读取该行,另一个仅将最后两个字符读取到char[2]缓冲区中。任何时候最后两个没有CR+LF,你知道线路有问题。这样,您就不用在循环中重复使用3002字符数组了。我并不反对创建自己的代码,但在使用它检查100000行时,效率非常重要。我简直不敢相信这不是其他人还没有遇到的东西,或者不是默认的f
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;
}