使用c#更新非常大的文件的最佳方法是什么

时间:2017-06-29 19:15:21

标签: c# large-files streamwriter

我没有询问只读大文件或读/写一个xml文件,我知道有一些Xml相关类来处理它。让我对我尝试做的事情进行更具体的描述:

我有一个非常大的文件大小,大约10TB,我无法一次加载到内存中。意思是,我不能这样做:

        var lines = File.ReadAllLines("LargeFile.txt");
        var t = 1 << 40;
        for(var i= t; i< 2 * t; i++)
        {
            lines[i] = someWork(); //
        }

        File.WriteAllLines("LargeFile.txt", lines);

我想读取和更新1到2TB范围内的行。

这样做的最佳方法是什么? .Net类或第三方库的示例会很有帮助。 我也对其他语言如何处理这个问题感兴趣。

我通过使用职位来尝试大卫的建议。 但是,我觉得它不起作用。 1. FileStream的大小似乎是固定的,我可以修改字节,但它会逐字节覆盖。它我的新数据大小/小于原始数据行。我无法正确更新。 2.我没有找到O(1)方法将行号转换为位置号。我仍然需要O(n)来找到这个位置。

下面是我的尝试

    public static void ReadWrite()
    {
        var fn = "LargeFile.txt";
        File.WriteAllLines(fn, Enumerable.Range(1, 20).Select(x => x.ToString()));

        var targetLine = 11; // zero based
        long pos = -1;
        using (var fs = new FileStream(fn, FileMode.Open, FileAccess.Read, FileShare.Read))
        {
            while (fs.Position != fs.Length)
            {
                if (targetLine == 0)
                {
                    pos = fs.Position +1; // move pos to begin of next line;
                }

                // still take average O(N) time to scan whole file to find the position.
                // I'm not sure if there is better way. to redirect to the pos of x line by O(1) time.
                if (fs.ReadByte() == '\n')
                {
                    targetLine--;
                }
            }
        }

        using (var fs = new FileStream(fn, FileMode.Open, FileAccess.ReadWrite))
        {
            var data = Encoding.UTF8.GetBytes("999"); 
            fs.Position = pos;
            // if the modify data has differnt size compare to the current one
            // it will overwrite next lines of data
            fs.Write(data, 0, data.Length);
        }
    }

1 个答案:

答案 0 :(得分:0)

您不必通读第一个1TB来修改文件的中间位置。 FileStream支持随机访问。 EG

    string fn = @"c:\temp\huge.dat";
    using (var fs = new FileStream(fn, FileMode.Open, FileAccess.Read, FileShare.Read))
    {

        fs.Position = (1024L * 1024L * 1024L);
        //. . .


    }

重新定位文件流后,您可以在当前位置读取和写入,或打开StreamReader从文件中读取文本。当然,您必须确保移动到以文件编码中的字符开头的字节偏移量。