我没有询问只读大文件或读/写一个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);
}
}
答案 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从文件中读取文本。当然,您必须确保移动到以文件编码中的字符开头的字节偏移量。