并行读取和处理c#中的100个文本文件

时间:2017-04-12 17:08:10

标签: c# multithreading file text parallel-processing

我有一个项目,读取100个文本文件,其中包含5000个单词。

我将单词插入列表中。我有第二个包含英语停用词的列表。我比较了两个列表并从第一个列表中删除了停用词。

运行应用程序需要1小时。我想要并行化它。我怎么能这样做?

继承我的代码:

    private void button1_Click(object sender, EventArgs e)
    {

        List<string> listt1 = new List<string>();
        string line;

        for (int ii = 1; ii <= 49; ii++)
        {

            string d = ii.ToString();
            using (StreamReader reader = new StreamReader(@"D" + d.ToString() + ".txt"))

            while ((line = reader.ReadLine()) != null)
            {

                string[] words = line.Split(' ');
                for (int i = 0; i < words.Length; i++)
                {
                    listt1.Add(words[i].ToString());



                }
            }

            listt1 = listt1.ConvertAll(d1 => d1.ToLower());

            StreamReader reader2 = new StreamReader("stopword.txt");
            List<string> listt2 = new List<string>();
            string line2;
            while ((line2 = reader2.ReadLine()) != null)
            {
                string[] words2 = line2.Split('\n');
                for (int i = 0; i < words2.Length; i++)
                {
                    listt2.Add(words2[i]);

                }
                listt2 = listt2.ConvertAll(d1 => d1.ToLower());

            }

            for (int i = 0; i < listt1.Count(); i++)
            {
                for (int j = 0; j < listt2.Count(); j++)
                {
                    listt1.RemoveAll(d1 => d1.Equals(listt2[j]));

                }
            }
            listt1=listt1.Distinct().ToList();


            textBox1.Text = listt1.Count().ToString();
        }
    }
  }
}

3 个答案:

答案 0 :(得分:2)

我用你的代码解决了很多问题。我认为你不需要多线程:

    private void RemoveStopWords()
    {
        HashSet<string> stopWords = new HashSet<string>();

        using (var stopWordReader = new StreamReader("stopword.txt"))
        {
            string line2;
            while ((line2 = stopWordReader.ReadLine()) != null)
            {

                string[] words2 = line2.Split('\n');
                for (int i = 0; i < words2.Length; i++)
                {
                    stopWords.Add(words2[i].ToLower());
                }
            }
        }

        var fileWords = new HashSet<string>();

        for (int fileNumber = 1; fileNumber <= 49; fileNumber++)
        {               
            using (var reader = new StreamReader("D" + fileNumber.ToString() + ".txt"))
            {
                string line;
                while ((line = reader.ReadLine()) != null)
                {
                    foreach(var word in line.Split(' '))
                    {
                        fileWords.Add(word.ToLower());
                    }
                }
            }
        }

        fileWords.ExceptWith(stopWords);

        textBox1.Text = fileWords.Count().ToString();


    }

您正在多次浏览停用词列表,并不断添加到列表中并重新尝试一次又一次地删除相同的停用词,因为您的代码的结构方式。您的需求也更好地匹配HashSet而不是List,因为它已经设置了基于操作和唯一性的处理。

如果您仍然希望将此并行,您可以通过读取禁用词列表一次并将其传递给将读取输入文件的异步方法,删除停用词并返回结果列表,然后您需要在异步调用返回后合并结果列表,但在决定需要之前你最好进行测试,因为这比这段代码已经有了更多的工作和复杂性。

答案 1 :(得分:1)

我在此处看到的一个有助于提高性能的问题是listt1.ConvertAll()将在列表中的O(n)中运行。您已经循环将项目添加到列表中,为什么不将它们转换为小写。另外,为什么不将单词存储在哈希集中,这样你就可以在O(1)中查找和插入。您可以将停用词列表存储在哈希集中,当您阅读文本输入时,查看该词是否为停用词,以及是否将其添加到哈希集以输出用户。

答案 2 :(得分:1)

如果我理解正确,你想:

  1. 将文件中的所有单词读入列表
  2. 删除所有&#34;停用词&#34;来自清单
  3. 重复99个以上的文件,只保存唯一的单词
  4. 如果这是正确的,代码非常简单:

    // This list will contain all the unique words from all 
    // the files, except the ones in the "stopWords" list
    var uniqueFilteredWords = filesToCheck.SelectMany(fileToCheck =>
        File.ReadAllText(fileToCheck)
            .Split(null)
            .Where(word => !string.IsNullOrWhiteSpace(word) &&
                           !stopWords.Any(stopWord => stopWord.Equals(word, 
                               StringComparison.OrdinalIgnoreCase)))
            .Distinct());
    

    这可以压缩成一行而没有显式循环:

    xmlhttp.open()

    此代码处理超过100个文件,每个文件超过12000个单词,不到一秒钟(WAY不到一秒...... 0.0001782秒)