如何将一个巨大的文件拆分成单词
本文关键字:巨大 文件 拆分 单词 一个 | 更新日期: 2023-09-27 18:01:13
如何从文本文件中读取一个很长的字符串,然后对其进行处理(拆分为单词(?
我尝试了StreamReader.ReadLine()
方法,但得到了OutOfMemory
异常。显然,我的队伍很长。这是我读取文件的代码:
using (var streamReader = File.OpenText(_filePath))
{
int lineNumber = 1;
string currentString = String.Empty;
while ((currentString = streamReader.ReadLine()) != null)
{
ProcessString(currentString, lineNumber);
Console.WriteLine("Line {0}", lineNumber);
lineNumber++;
}
}
以及将行拆分为单词的代码:
var wordPattern = @"'w+";
var matchCollection = Regex.Matches(text, wordPattern);
var words = (from Match word in matchCollection
select word.Value.ToLowerInvariant()).ToList();
您可以通过char进行读取,边读边构建单词,使用yield
使其延迟,这样您就不必一次读取整个文件:
private static IEnumerable<string> ReadWords(string filename)
{
using (var reader = new StreamReader(filename))
{
var builder = new StringBuilder();
while (!reader.EndOfStream)
{
char c = (char)reader.Read();
// Mimics regex /w/ - almost.
if (char.IsLetterOrDigit(c) || c == '_')
{
builder.Append(c);
}
else
{
if (builder.Length > 0)
{
yield return builder.ToString();
builder.Clear();
}
}
}
yield return builder.ToString();
}
}
代码按字符读取文件,当遇到非单词字符时,它将yield return
在此之前构建的单词(仅用于第一个非字母字符(。该代码使用StringBuilder
来构建字符串。
Char.IsLetterOrDigit()
的行为与字符的正则表达式单词字符w
一样,但下划线(以及其他(也属于后一类。如果您的输入包含更多您也希望包含的字符,则必须更改if()
。
将其切成比特大小的部分。因此,与其尝试读取4gb(我认为大约一页大小(,不如尝试读取8个500mb的块,这应该会有所帮助。
垃圾回收可能是一种解决方案。我真的不确定这是否是问题的根源。但如果是这样的话,一个简单的GC.Collect通常效率不高,而且出于性能原因,只有在真正需要的时候才应该调用它。当可用内存太低(低于作为过程参数提供的阈值(时,请尝试以下过程调用垃圾。
int charReadSinceLastMemCheck = 0 ;
using (var streamReader = File.OpenText(_filePath))
{
int lineNumber = 1;
string currentString = String.Empty;
while ((currentString = streamReader.ReadLine()) != null)
{
ProcessString(currentString, lineNumber);
Console.WriteLine("Line {0}", lineNumber);
lineNumber++;
totalRead+=currentString.Length ;
if (charReadSinceLastMemCheck>1000000)
{ // Check memory left every Mb read, and collect garbage if required
CollectGarbage(100) ;
charReadSinceLastMemCheck=0 ;
}
}
}
internal static void CollectGarbage(int SizeToAllocateInMo)
{
long [,] TheArray ;
try { TheArray =new long[SizeToAllocateInMo,125000]; }low function
catch { TheArray=null ; GC.Collect() ; GC.WaitForPendingFinalizers() ; GC.Collect() ; }
TheArray=null ;
}