用 C# 更新一个非常大的文件的最佳方法是什么

What's best way to update a very large file with c#

我问的不是只读取一个大文件或 reading/writing 一个 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 类 或第 3 方库的示例会有所帮助。 我也对其他语言如何处理这个问题感兴趣。


我通过使用 position 尝试了 David 的建议。 但是,我觉得它不起作用。 1. FileStream的大小好像是固定的,我可以按字节修改,但是会逐字节覆盖。我的新数据大小比原始数据行大 large/less。我将无法正确更新。 2. 我没有找到将第 num 行转换为第 num 个位置的 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);
        }
    }

您不必通读前 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 从文件中读取文本。当然,您必须确保移动到文件编码中字符开始的字节偏移量。