1

I want to implement "Find in Files" similar to one in IDE's using lucene. Basically wants to search in source code files like .c,.cpp,.h,.cs and .xml. I tried the demo shown in apache website. It returns the list of files without line numbers and number of occurance in that file. I am sure there should be some ways to get it.

Is there anyway to get those details?

4

2 回答 2

1

你能分享一下apache网站上显示的演示链接吗?

在这里,我向您展示如何获取给定文档集的术语的术语频率:

public static void main(final String[] args) throws CorruptIndexException,
            LockObtainFailedException, IOException {

        // Create the index
        final Directory directory = new RAMDirectory();
        final Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_36);
        final IndexWriterConfig config = new IndexWriterConfig(
                Version.LUCENE_36, analyzer);
        final IndexWriter writer = new IndexWriter(directory, config);

        // addDoc(writer, field, text);
        addDoc(writer, "title", "foo");
        addDoc(writer, "title", "buz qux");
        addDoc(writer, "title", "foo foo bar");

        // Search
        final IndexReader reader = IndexReader.open(writer, false);
        final IndexSearcher searcher = new IndexSearcher(reader);

        final Term term = new Term("title", "foo");
        final Query query = new TermQuery(term);
        System.out.println("Query: " + query.toString() + "\n");

        final int limitShow = 3;
        final TopDocs td = searcher.search(query, limitShow);
        final ScoreDoc[] hits = td.scoreDocs;

        // Take IDs and frequencies
        final int[] docIDs = new int[td.totalHits];
        for (int i = 0; i < td.totalHits; i++) {
            docIDs[i] = hits[i].doc;
        }
        final Map<Integer, Integer> id2freq = getFrequencies(reader, term,
                docIDs);

        // Show results
        for (int i = 0; i < td.totalHits; i++) {
            final int docNum = hits[i].doc;
            final Document doc = searcher.doc(docNum);
            System.out.println("\tposition " + i);
            System.out.println("Title: " + doc.get("title"));
            final int freq = id2freq.get(docNum);
            System.out.println("Occurrences of \"" + term.text() + "\" in \""
                    + term.field() + "\" = " + freq);
            System.out.println("--------------------------------\n");
        }
        searcher.close();
        reader.close();
        writer.close();
    }

这里我们将文档添加到索引中:

private static void addDoc(final IndexWriter w, final String field,
            final String text) throws CorruptIndexException, IOException {
        final Document doc = new Document();
        doc.add(new Field(field, text, Field.Store.YES, Field.Index.ANALYZED));
        doc.add(new Field(field, text, Field.Store.YES, Field.Index.ANALYZED));
        w.addDocument(doc);
}

这是一个如何获取文档中术语出现次数的示例:

public static Map<Integer, Integer> getFrequencies(
        final IndexReader reader, final Term term, final int[] docIDs)
        throws CorruptIndexException, IOException {
    final Map<Integer, Integer> id2freq = new HashMap<Integer, Integer>();
    final TermDocs tds = reader.termDocs(term);
    if (tds != null) {
        for (final int docID : docIDs) {
            // Skip to the next docID
            tds.skipTo(docID);
            // Get its term frequency
            id2freq.put(docID, tds.freq());
        }
    }
    return id2freq;
}

如果将所有内容放在一起并运行它,您将获得以下输出:

Query: title:foo

    position 0
Title: foo
Occurrences of "foo" in "title" = 2
--------------------------------

    position 1
Title: foo foo bar
Occurrences of "foo" in "title" = 4
--------------------------------
于 2013-06-20T14:35:45.703 回答
0

我试过很多论坛,响应为零。所以最后我从@Luca Mastrostefano 的回答中得到了一个想法,以获取行号详细信息。

来自 lucene searcher 的 Taginfo 返回文件名。我认为这足以获得行号。Lucene 索引不是存储实际内容,它实际上是存储哈希值。所以不可能直接得到行号。因此,我认为唯一的方法是使用该路径并读取文件并获取行号。

public static void PrintLines(string filepath,string key)
    {
        int counter = 1;
        string line;

        // Read the file and display it line by line.
        System.IO.StreamReader file = new System.IO.StreamReader(filepath);
        while ((line = file.ReadLine()) != null)
        {
            if (line.Contains(key))
            {
                Console.WriteLine("\t"+counter.ToString() + ": " + line);
            }
            counter++;
        }
        file.Close();
    }

在来自 lucene 搜索器的路径之后调用此函数。

于 2013-06-25T14:53:56.857 回答