日期:2014-05-17  浏览次数:21092 次

C# 大数据量代码性能优化
直接上代码,现在用时大约在2分钟以上
C# code

static void ParseTxt()
        {
            /*
             * a.txt 数据
             * 操作系统确定程序是否成功执行完毕
             * 函数体函数定义的最后部分
             * 程序编写完后需要进行编译
             * 标准库定义了 4 个 IO 对象
             * 系统将这些对象与执行程序的窗口联系起来
             * 编译器要使用库
             * 
             * b.txt 数据
             * 讲解
             * 函数部分
             * 程序编译
             * 标准库对象
             * 系统窗口
             * 编译器讲解
             * 
             * 解析后新生成的newa.txt应该是这样的
             * 操作系统确定程序是否成功执行完毕   【未找到】
             * 函数体函数定义的最后部分 体函数定义的最后部分
             * 程序编写完后需要进行编译 编写完后需要进行编译
             * 标准库定义了 4 个 IO 对象    定义了 4 个 IO 对象
             * 系统将这些对象与执行程序的窗口联系起来   将这些对象与执行程序的窗口联系起来
             * 编译器要使用库   要使用库
             */
            string aPath = "a.txt";//16W+数据
            string bPath = "b.txt";//2000+数据
            string newaPath = "newa.txt";//与a.txt数据量相同
            string[] arrA = File.ReadAllLines(aPath);
            string[] arrB = File.ReadAllLines(bPath);
            StringBuilder sb = new StringBuilder();
            bool isHave = false;
            string titleTrim = string.Empty;
            string subTitle = string.Empty;
            char[] sChar = new char[] { ' ', '[', '[', '(', '『', '(', '{', '【' };
            char[] eChar = new char[] { ' ', ']', '+', '/', '』', ']', ')', '-', '}', '】' };
            foreach (string title in arrA)
            {
                titleTrim = title.TrimStart(sChar);
                for (int i = 2; i < titleTrim.Length; i++)
                {
                    isHave = false;
                    subTitle = titleTrim.Substring(0, i);
                    foreach (string b in arrB)
                    {
                        if (b.Contains(subTitle))
                        {
                            isHave = true;
                            break;
                        }
                    }
                    if (!isHave)
                    {
                        if (i == 2)
                        {
                            sb.Append(title + "\t【未找到】\r\n");
                        }
                        else
                        {
                            sb.Append(title + "\t" + titleTrim.Substring(i - 1, titleTrim.Length - i + 1).TrimStart(eChar) + "\r\n");
                        }
                        break;
                    }
                }
            }
            File.WriteAllText(newaPath, sb.ToString());
        }



------解决方案--------------------
大致看了一下代码,似乎是在B中查找A中的串,然后把匹配的结果存入C。期间要把A的左右括号去掉。

我在想,利用正则表达式Regex.Replace(),是不是会好一些?这比你反复地取用同一个串,在B中进行遍历应该会效率许多。

其中每次查找的Regex,根据A中单词的不同进行动态构造,然后在B中进行Replace。具体的我还没细想。
------解决方案--------------------
我觉得是:
subTitle = titleTrim.Substring(0, i);
foreach (string b in arrB)
{
if (b.Contains(subTitle))
{
isHave = true;
break;
}
}
这里最浪费时间,要优化
------解决方案--------------------
就你目前的这个方法,如果想提高效率,可以使用多线程。
string[] arrA = File.ReadAllLines(aPath);

这个数据比较大(16W+),建立10个线程,
每一个线程读取16000的数据,每个线程里的arrB(2000)都是全部数据,
这样处理的话,初步估计在30秒内可以完成
------解决方案--------------------
探讨
现在要30秒+了
正则表达式不知道写合适,就想着怎么优化(好昵称都被占用了) 说的那段代码,我是这么优化的,就是把arrB换成了string b