如何从文本文件中读取一个非常长的字符串,然后处理它(拆分成单词)?
我尝试了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();
答案 0 :(得分:5)
您可以通过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()
对于字符的行为与the regex word character w
一样,但下划线(以及其他)也属于后一类。如果您的输入包含更多您希望包含的字符,则必须更改if()
。
答案 1 :(得分:0)
将其剪切为比特大小的部分。因此,不要试图读取4gb,我认为这是关于页面的大小,尝试阅读8 500mb块,这应该有所帮助。
答案 2 :(得分:0)
垃圾收集可能是一种解决方案。我不确定这是问题来源。但如果是这种情况,简单的GC.Collect通常效率不高,出于性能原因,只有在真正需要时才应该调用它。当可用内存过低(低于作为过程参数提供的阈值)时,请尝试以下过程调用垃圾。
sync.exe "profile name or id"