ASP源码
PHP源码
.NET源码
JSP源码
一. 我本来的程序
其实我本来的程序挺简单, 完全修改自Demo里面的SearchFiles和IndexFiles. 唯一不同的是引用了SmartCN的分词器.
我把修改那一点的代码贴出来.
In***hChinese.java:
Date start = new Date();try { IndexWriter writer = new IndexWriter(FS***ectory.open(INDEX_DIR), new SmartChineseAnalyzer(Ve***on.LUCENE_CURRENT), true, In***Writer.MaxFieldLength.LIMITED); indexDocs(writer, docDir); Sy***m.out.println("Indexing to directory '" +INDEX_DIR+ "'..."); Sy***m.out.println("Optimizing..."); //***ter.optimize(); wr***r.close(); Date end = new Date(); Sy***m.out.println(en***etTime() - st***.getTime() + " total milliseconds"); }
Se***hChinese.java
Analyzer analyzer = new SmartChineseAnalyzer(Ve***on.LUCENE_CURRENT); BufferedReader in = null;if (queries != null) { in = new BufferedReader(new FileReader(queries));} else { in = new BufferedReader(new InputStreamReader(Sy***m.in, "GBK"));}
在这里, 我制定了输入的查询是采用GBK编码的.
然后我充满信心的运行后......发现无法检索出中文, 里面的英文检索是正常的.
二. 发现问题.
于是我就郁闷了, 由于对于java与lucene都是太熟悉, 而且用的3.0.0版外面的讨论又不是太多, 就瞎折腾了一会儿, 发现我如果把文件的格式另存为ansi就可以检索中文了(以前是utf-8的), 看来是文件编码的问题, 摸索了一下, 在in***Chinese.java中发现了如下的代码:
static void indexDocs(IndexWriter writer, File file) throws IOException { // do not try to index files that cannot be read if (fi***canRead()) { if (fi***isDirectory()) { String[] files = fi***list(); // an IO error could occur if (files != null) { for (int i = 0; i < fi***.length; i++) { indexDocs(writer, new File(file, files[i])); } } } else { Sy***m.out.println("adding " + file); try { wr***r.addDocument(Fi***ocument.Document(file)); } // at least on windows, some temporary files raise this exception with an "access denied" message // checking if the file can be read doesn't help catch (FileNotFoundException fnfe) { ; } } }
重点在于这一句:
try { wr***r.addDocument(Fi***ocument.Document(file));}
读取文件的代码应该就在这里面, 跟踪进去:
public static Document Document(File f) throws ja***io.FileNotFoundException, UnsupportedEncodingException { Document doc = new Document(); doc.add(new Field("path", f.***Path(), Fi***.Store.YES, Fi***.Index.NOT_ANALYZED)); doc.add(new Field("modified", Da***ools.timeToString(f.***tModified(), Da***ools.Resolution.MINUTE), Fi***.Store.YES, Fi***.Index.NOT_ANALYZED)); doc.add(new Field("contents", FileReader(f))); // return the document return doc;} private FileDocument() {}}
这是Lucene的一个内部类, 作用就是从一个文本文件中获取内容, 生成的Document默认有3个域: path, modified, content, 而content就是文件的文本内容了. 看来是FileReader(f), 这个函数出了问题了, 根本没有制定采用什么编码进行读取啊, 于是把这儿简单的修改了一下.
FileInputStream fis=new FileInputStream(f);// 按照 UTF-8 编码方式将字节流转化为字符流InputStreamReader isr=new InputStreamReader(fis,"UNICODE");// 从字符流中获取文本并进行缓冲BufferedReader br=new BufferedReader(isr); doc.add(new Field("contents", br));
至于那个"Unicode"可以修改为支持的所有编码, 当我修改为"utf-8"后就可以正常使用了.
三. 一些猜测:
对于Lucene索引文件的时候, 编码是没有关系的, 只要正确指定了, 那么输出的文件都是可以被正常检索到的, 也就是说, 不同的编码文件索引后的结果一样(求证)