zoukankan      html  css  js  c++  java
  • WEBUS2.0 In Action

    最近由于工作的需要, 要分析大量C#代码, 在数万个cs文件中搜索特定关键词. 这是一项非常耗时的工作, 用Notepad++要运行接近半个小时. 于是我利用WEBUS2.0 SDK创建了一个代码搜索器程序, 非常方便的完成了这项工作.

    Code Search程序首先会在选定的目录中搜索所有cs文件:

        private void btnOpen_Click(object sender, EventArgs e)
            {
                try
                {
                    if (folderBrowserDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                    {
                        Task.Factory.StartNew(IndexProc);
                        //...
            }

    然后创建IIndexer, 并在一个线程中为所有找到的文件编制索引:

            void IndexProc()
            {
                var files = Directory.GetFiles(folderBrowserDialog1.SelectedPath, "*.cs", SearchOption.AllDirectories);
                if (files != null && files.Length > 0)
                {
                    //...this.ResetIndex();
                    foreach (var file in files)
                    {
                        Document doc = new Document();
                        doc.Fields.Add(new Field("FileName", file, FieldAttributes.None));
                        doc.Fields.Add(new Field("Code", StringHelper.LoadString(file), FieldAttributes.AnalyseIndex));
                        m_Index.Add(doc);
                        //...
                    }
                }
                //...
            }
    
            void ResetIndex()
            {
                if (m_Index != null)
                {
                    m_Index.Close();
                }
                m_Index = new IndexManager(new CodeAnalyzer());
                m_Index.DumpDocs = 3000;
                m_Index.DumpSize = 10;
                m_Index.MinIndexSize = int.MaxValue;
                m_Index.MaxIndexSize = int.MaxValue;
                m_Index.MergeFactor = int.MaxValue;
                m_Index.New(AppDomain.CurrentDomain.BaseDirectory + @"Index");
                m_Searcher = new IndexSearcher(m_Index);
            }

    通过调节DumpDocs和DumpSize, 可以优化程序的内存占用;

    通过调节Min/MaxIndexSize和MergeFactor, 可以优化程序的IO性能, 目前我设置的MinIndexSize最大意味着自始至终只会生成一个索引片段; MergeFactor最大意味着从不合并索引片段.

    在创建索引的时候, 我们使用的是专门为代码分析设计的IAnalyzer:

        class CodeAnalyzer : IAnalyzer
        {
            //...public ITokenStream GetTokenStream(Webus.Documents.Field field)
            {
                if (field.Name == "Code")
                {
                    return this.GetTokenStream(field.Value.ToString());
                }
                else
                {
                    return null;
                }
            }
        }
    
        class CodeTokenStream : ITokenStream
        {
            HashSet<string> stops = new HashSet<string>(new string[] { 
                "abstract",
                "event",    
                "new",    
                //... 
                "enum",    
                "namespace",    
                "string"
            });
            Queue<Token> m_Buffer = new Queue<Token>();
            public CodeTokenStream(string text)
            {
                MatchCollection mc = Regex.Matches(text, @"w+");
                foreach (Match m in mc)
                {
                    var key = m.Value.ToLower();
                    if (stops.Contains(key) == false)
                    {
                        m_Buffer.Enqueue(new Token(key, m.Index, m.Length));
                    }
                }
            }
            //...
    }

    这个分析器中包含了所有C#的关键词, 由于他们是绝对高频词并且没有搜索的意义, 因此在分析的时候会跳过这些词汇而不做任何处理. 

    在编制索引的时候通过事件将状态更新到UI上面:

            private void frmCodeSearch_Load(object sender, EventArgs e)
            {
                try
                {
                    this.StatusChanged += new StatusChangeEventHandler(frmCodeSearch_StatusChanged);
                    //...
            }
    
            delegate void UpdateUI();
            void frmCodeSearch_StatusChanged(object sender, string status)
            {
                this.Invoke(new UpdateUI(() => { this.txtStatus.Text = status; }));
            }

    这里是跨线程更新UI, 因此需要使用this.Invoke来封送相应操作. 

    索引编制过程中就可以开始搜索了:

    对应代码如下:

            private void txtKeyword_TextChanged(object sender, EventArgs e)
            {
                try
                {
                    TermQuery query = new TermQuery(new Term("Code", txtKeyword.Text.ToLower()));
                    var hits = m_Searcher.Search(query);
                    List<SearchResult> result = new List<SearchResult>();
                    foreach (HitDoc hit in hits)
                    {
                        StandardHighlighter hl = new StandardHighlighter(hit);
                        result.Add(new SearchResult(hit));
                    }
                    dgvResult.DataSource = result;
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ExceptionHelper.ToString(ex));
                }
            }

    创建一个TermQuery对象, 对Code字段进行搜索, 构建List<SearchResult>类型的结果集, 并且绑定到DataGridView上面, 大功告成! enjoy~!

    下载源代码

    阅读更多WEBUS2.0 SDK文章

    2013-7-21补充: 

    增强了搜索功能, 支持WEBUS2.0 SDK的查询表达式, 能够完成各种复杂的搜索任务. 具体语法将在后面的文章中介绍. 

    2013-8-20补充: 

    Build - 选择一个文件夹开始编制索引, 编好的索引自动保存在当前目录的CodeSearch.Index子目录下面. 比如我们选择C:SourceCode来编制索引, 这索引数据会保存在C:SourceCodeCodeSearch.Index中. 

    Open - 打开已经存在的索引, 即上面所说的CodeSearch.Index文件夹. 

    关闭程序时会自动关闭当前索引. 索引关闭后全部数据都保存到磁盘上, 下次可以直接打开来继续使用. 

  • 相关阅读:
    【Uvalive4960】 Sensor network (苗条树,进化版)
    【UVA 1151】 Buy or Build (有某些特别的东东的最小生成树)
    【UVA 1395】 Slim Span (苗条树)
    【UVA 10600】 ACM Contest and Blackout(最小生成树和次小生成树)
    【UVA 10369】 Arctic Network (最小生成树)
    【UVA 10816】 Travel in Desert (最小瓶颈树+最短路)
    【UVA 11183】 Teen Girl Squad (定根MDST)
    【UVA 11865】 Stream My Contest (二分+MDST最小树形图)
    【UVA 11354】 Bond (最小瓶颈生成树、树上倍增)
    【LA 5713 】 Qin Shi Huang's National Road System (MST)
  • 原文地址:https://www.cnblogs.com/iamzyf/p/3199434.html
Copyright © 2011-2022 走看看