我有几个txt文件,每个文件包含超过300万行。每行包含客户的连接,其中有客户 ID、IP 地址......
我需要找到特定的 IP 地址并获取与其相关的客户 ID。
我读取该文件并将其拆分为一个数组,并通过 foreach 在每一行中进行搜索,但由于有很多行,因此出现以下错误。
引发了“System.OutOfMemoryException”类型的异常。
我应该解压缩 txt 文件,因为它们是压缩的。我使用下面的代码:
string decompressTxt = decompressTxt = this.Decompress(new FileInfo(filePath));
char[] delRow = { '\n' };
string[] rows = decompressTxt.Split(delRow);
for (int i = 0; i < rows.Length; i++){
if(rows[i].Contains(ip)){
}
}
string Decompress(FileInfo fileToDecompress)
{
string newFileName = "";
string newFIleText = "";
using (FileStream originalFileStream =fileToDecompress.OpenRead())
{
string currentFileName = fileToDecompress.FullName;
newFileName = currentFileName.Remove(currentFileName.Length - fileToDecompress.Extension.Length);
using (FileStream decompressedFileStream = File.Create(newFileName))
{
using (GZipStream decompressionStream = new GZipStream(originalFileStream, CompressionMode.Decompress))
{
decompressionStream.CopyTo(decompressedFileStream);
}
}
newFIleText = File.ReadAllText(newFileName);
File.Delete(newFileName);
}
return newFIleText;
}
好吧,即使在我们了解内存不足的原因之前,您正在做的很多事情都是不必要的。
首先解压不需要中间文件,
GZipStream
直接读取即可。但是等等,您是否认为您必须用来File.ReadAllText
读取文本,因此这就是您首先解压缩文件的原因?那是没有必要的。当您想从流中读取文本时,只需使用 a 即可
StreamReader
(这就是File.ReadAllText
下面的用法)。该阅读器还可以用于逐行读取,而无需将整个文件放入内存中,只需每次一行读取每一行。只要打电话
ReadLine()
直到它返回null
。将所有内容放在一起,下面的代码可以解压缩数据并一次读取一行,而无需拆分任何内容。它不仅可以扩展非常大的文件,而且速度也更快。
您需要将文件作为可枚举的行来处理。不要将其复制到另一个
MemoryStream
或将其复制到字符串中。StreamReader
可以逐行处理。您绝对不需要另一个文件来解压缩它然后读回它。
总之,您不需要将整个文件一次性保存在内存中。
还有更有效的方法,例如将数据分割为字节块,但这要复杂得多。
您可能还应该考虑
async
, 以及编码。