如何将一个巨大的文件分成单词?

时间:2015-07-06 21:34:06

标签: c# .net file-io

如何从文本文件中读取一个非常长的字符串,然后处理它(拆分成单词)?

我尝试了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();

3 个答案:

答案 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"