Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/305.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何将一个巨大的文件拆分成单词?_C#_.net_File Io - Fatal编程技术网

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

C# 如何将一个巨大的文件拆分成单词?,c#,.net,file-io,C#,.net,File Io,如何从文本文件中读取很长的字符串,然后进行处理(拆分为单词) 我尝试了StreamReader.ReadLine()方法,但得到了OutOfMemory异常。显然,我的台词非常长。 这是我读取文件的代码: using (var streamReader = File.OpenText(_filePath)) { int lineNumber = 1; string currentString = String.Empty; while (

如何从文本文件中读取很长的字符串,然后进行处理(拆分为单词)

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

把它切成小块。因此,与其尝试读取4gb(我认为大约是一页大小),不如尝试读取8个500mb的数据块,这应该会有所帮助。

您可以按字符读取,边读边积累单词,使用
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();
    }
}
私有静态IEnumerable可读字(字符串文件名)
{
使用(var reader=newstreamreader(文件名))
{
var builder=新的StringBuilder();
而(!reader.EndOfStream)
{
char c=(char)reader.Read();
//模仿regex/w/-small。
if(char.IsleterOrdigit(c)| | c=='|'
{
附加(c);
}
其他的
{
如果(builder.Length>0)
{
收益率返回生成器.ToString();
builder.Clear();
}
}
}
收益率返回生成器.ToString();
}
}
代码按字符读取文件,当遇到非单词字符时,它将返回在此之前建立的单词(仅针对第一个非字母字符)。代码使用
StringBuilder
构建单词字符串


与字符的行为相同,但下划线(除其他外)也属于后一类。如果您的输入包含更多您希望包含的字符,则必须更改
If()

垃圾收集可能是一种解决方案。我不确定这是否是问题的根源。但是如果是这样的话,一个简单的GC.Collect通常是不够的,并且出于性能原因,应该只在真正需要时调用它。尝试以下过程,当可用内存过低(低于作为过程参数提供的阈值)时调用垃圾


您在拆分操作中使用了什么算法/方法?@byako,下面是我用于此操作的方法:
public static IEnumerable GetLowercasedWords(字符串文本){if(string.IsNullOrEmpty(text)){return null;}var wordPattern=@“\w+”;var matchCollection=Regex.Matches(text,wordPattern);var words=(从matchCollection中的Match word选择word.Value.ToLowerInvariant()).ToList();return words;}
抱歉格式化。最好添加您实际实现StreamReader的方式,所以人们可能会在那里发现错误。问题没有140个字符的限制。@Jens,当然,我在问题中添加了代码。请添加您的用例,例如,您对单词做了什么,是否要计算出现次数,获取唯一的单词列表,等等?它可以提供进一步的优化可能性。我应该说,您不会将其拆分为精确的块。但是相对来说,足够近的块。我这样说的原因是,如果你有一个500 mb的截止值,你会希望在一个单词的结尾或开头分开文件,而不是在中间。所以不要只是把文件切碎。用更聪明的方式做.你是对的。这就是我遇到困难的主要原因。
StringBuilder
不是这种方法的更好选择吗?小心!这与
\w+
不同,因为它只处理空格(如破折号、标点符号)。
\w
还包括数字和下划线。在这种情况下,word是[A-Za-z0-9]的序列,这可以工作,但CPU负载将非常大。逐字符处理真的很昂贵。更新:每秒30兆,这比我预期的要多得多。@CodeCaster:你在删除的评论中写道“你也不应该跨越在某个法国论坛上找到的巫毒密码”。如果复制你已经在另一个论坛上发布的代码是违反StackOverflow原则的,我将很快离开这个论坛。如果你看看法国论坛回复的作者,你会发现它的名字也是“涂鸦”。但你肯定认为这是另一个人。涂鸦,你的垃圾收集方法是魔鬼。我从你先前的回答中认出了这一点。
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 ;
}