从巨大的文本文件中读取特定行(c#4.0)

时间:2013-11-02 17:41:19

标签: c# io large-files

编辑: @Everyone抱歉,我觉得与int32的大小混淆了。问题可能已经结束,但由于已有几个答案,我选择了第一个答案。 原始问题在下面供参考


我正在寻找一种从非常大的文本文件加载特定行的方法,我正在计划使用File.ReadLines和Skip()方法:

File.ReadLines(fileName).Skip(nbLines).Take(1).ToArray();

问题是,Skip()int值,而int值限制在200万左右。应该适用于大多数文件,但是如果文件包含的内容,比如2000万行?我尝试使用long,但没有重载Skip()接受longs。

行是可变的,未知的长度,所以我不能计算字节数。

是否有一个选项不涉及逐行阅读或将文件拆分成块?此操作必须非常快。

4 个答案:

答案 0 :(得分:5)

整数是32位数字,因此限制为2 十亿左右。

也就是说,如果你必须从文件中读取一个随机行,而你所知道的是文件中有行,你必须逐行读取它,直到你到达你想要的行。您可以使用一些缓冲区来稍微缓解I / O(默认情况下它们处于打开状态),但是您不会获得比这更好的性能。

除非,否则您将更改文件的保存方式。如果您可以创建一个索引文件,包含主文件的每一行的位置,您可以更快地读取一行。

嗯,不是无限的,但是很多更快 - 从O(N)到几乎O(1)(差不多,因为寻找文件中的随机字节可能不是O( 1)操作,取决于操作系统的操作方式。)

答案 1 :(得分:3)

我投票决定关闭你的问题,因为你的前提不正确。但是,这是一个真正的问题,没有什么可以阻止你编写自己的Skip扩展方法,该方法需要long而不是int

public static class SkipEx
{
    public static IEnumerable<T> LongSkip<T>(this IEnumerable<T> src, 
                                             long numToSkip)
    {
        long counter = 0L;
        foreach(var item in src)
        {
            if(counter++ < numToSkip)continue;
            yield return item;
        }
    }
}

所以现在你可以做到这样的疯狂

File.GetLines(filename).LongSkip(100000000000L)
没有问题(明年再来......)。多田!

答案 2 :(得分:2)

Int值限制在2 10亿而不是200万。因此,除非你的文件将超过大约2.4 十亿行,否则你应该没问题。

答案 3 :(得分:1)

您始终可以使用SkipWhileTakeWhile,并编写自己的谓词