- 浏览: 95563 次
- 性别:
- 来自: 武汉
文章分类
最新评论
-
fengweiyou:
只取当前年月日 TRUNC(SYSDATE) 就可以了
oracle函数只取年月日 -
spp_1987:
我在页面上 显示出来的 怎么是乱码啊。 能解决下吗
是什 ...
struts+jquery -
spp_1987:
//JSONObject json = JSONObject. ...
struts+jquery -
spp_1987:
不知道为什么 有错啊。 我用的是DispatchAction啊 ...
struts+jquery -
hiteny:
还是css用着方便@ 谢谢啦
css控制字符串显示长度
Directory抽象类比较常用的具体实现子类应该是FSDirectory类和RAMDirectory类。FSDirectory类是与文件系统的目录相关的,而RAMDirectory类是与内存相关的,即是指内存中的一个临时非永久的区域。
FSDirectory类源代码定义如下:
上面FSDirectory类的实现挺复杂的,主要是在继承Directory抽象类的基础上,增加了文件系统目录锁特有的一些操作方式。
通过FSDirectory类源代码的阅读,关于文件系统目录FSDirectory类,总结几点:
1、锁工厂的获取及其管理;
2、对文件系统目录下索引文件的输入流和输出流的管理;
3、获取FSDirectory类实例;
4、获取锁工厂实例后,可以创建一个新的FSDirectory类实例,在此之前先要完成一些初始化工作;
5、继承自Directory抽象类,自然可以实现索引文件的的拷贝操作。
6、FSDirectory类中实现了很多静态内部类,这使得只能在FSDirectory类内部访问这些静态类,对外部透明。
FSDirectory类源代码定义如下:
package org.apache.lucene.store; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.RandomAccessFile; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Hashtable; import org.apache.lucene.index.IndexFileNameFilter; import org.apache.lucene.index.IndexWriter; public class FSDirectory extends Directory { // DIRECTORIES需要进行同步,用于存放指定键值对<File,FSDirectory> private static final Hashtable DIRECTORIES = new Hashtable(); private static boolean disableLocks = false; /** * 设置锁文件是否可以使用 * They should only be disabled if the index * is on a read-only medium like a CD-ROM. */ public static void setDisableLocks(boolean doDisableLocks) { FSDirectory.disableLocks = doDisableLocks; } // 获取锁文件是否可以使用,返回true表示不可以使用 public static boolean getDisableLocks() { return FSDirectory.disableLocks; } // 锁目录,该属性已经废弃 public static final String LOCK_DIR = System.getProperty( "org.apache.lucene.lockDir", System.getProperty("java.io.tmpdir")); // 定义一个静态内部类,该类是基于文件系统的 private static Class IMPL; static { try { String name = System.getProperty( "org.apache.lucene.FSDirectory.class", FSDirectory.class .getName()); IMPL = Class.forName(name); } catch (ClassNotFoundException e) { throw new RuntimeException("cannot load FSDirectory class: " + e.toString(), e); } catch (SecurityException se) { try { IMPL = Class.forName(FSDirectory.class.getName()); } catch (ClassNotFoundException e) { throw new RuntimeException( "cannot load default FSDirectory class: " + e.toString(), e); } } } private static MessageDigest DIGESTER; static { try { DIGESTER = MessageDigest.getInstance("MD5"); } catch (NoSuchAlgorithmException e) { throw new RuntimeException(e.toString(), e); } } /** A buffer optionally used in renameTo method */ private byte[] buffer = null; // 静态方法,根据指定的路径path,返回该路径的一个FSDirectiry实例 public static FSDirectory getDirectory(String path) throws IOException { return getDirectory(new File(path), null); } // 静态方法,根据指定的路径path以及锁工厂LockFactory参数,返回该路径的一个FSDirectiry实例 public static FSDirectory getDirectory(String path, LockFactory lockFactory) throws IOException { return getDirectory(new File(path), lockFactory); } // 静态方法,根据指定的File对象,返回该路径的一个FSDirectiry实例 public static FSDirectory getDirectory(File file) throws IOException { return getDirectory(file, null); } // 静态方法,根据指定File对象以及锁工厂LockFactory参数,返回该路径的一个FSDirectiry实例 // 该方法是获取FSDirectiry实例的核心方法,其他重载的该方法都是经过转换,调用该方法实现的 public static FSDirectory getDirectory(File file, LockFactory lockFactory) throws IOException { file = new File(file.getCanonicalPath()); if (file.exists() && !file.isDirectory()) // 如果file存在并且不是一个目录文件,抛出异常 throw new IOException(file + " not a directory"); if (!file.exists()) // 如果file不存在 if (!file.mkdirs()) // 如果创建由file指定的路径名所指定的目录失败,则很可能已经存在,抛出异常 throw new IOException("Cannot create directory: " + file); FSDirectory dir; synchronized (DIRECTORIES) { dir = (FSDirectory) DIRECTORIES.get(file); if (dir == null) { try { dir = (FSDirectory) IMPL.newInstance(); // 调用静态内部类IMPL获取一个与文件系统目录有关的Directory类,并加载该类 } catch (Exception e) { throw new RuntimeException( "cannot load FSDirectory class: " + e.toString(), e); // 加载失败 } dir.init(file, lockFactory); // 根据指定的file和lockFactory,调用该类Directory的init方法,进行FSDirectory的初始化初始化工作 DIRECTORIES.put(file, dir); } else { // 如果该目录dir管理所用的锁工厂实例为空,或者不是同一个锁工厂实例,抛出异常 if (lockFactory != null && lockFactory != dir.getLockFactory()) { throw new IOException( "Directory was previously created with a different LockFactory instance; please pass null as the lockFactory instance and use setLockFactory to change it"); } } } synchronized (dir) { dir.refCount++; // 用于记录该目录dir被引用的计数增加1 } return dir; } // 获取FSDirectory实例,该方法已经废弃 public static FSDirectory getDirectory(String path, boolean create) throws IOException { return getDirectory(new File(path), create); } // 获取FSDirectory实例,该方法已经废弃 public static FSDirectory getDirectory(File file, boolean create) throws IOException { FSDirectory dir = getDirectory(file, null); // This is now deprecated (creation should only be done // by IndexWriter): if (create) { dir.create(); } return dir; } private void create() throws IOException { if (directory.exists()) { // File directory是FSDirectory类的一个成员 String[] files = directory.list(IndexFileNameFilter.getFilter()); // 获取经过IndexFileNameFilter过滤后的该目录文件directory下的文件列表 if (files == null) // 如果获取的文件列表为空 throw new IOException("cannot read directory " + directory.getAbsolutePath() + ": list() returned null"); for (int i = 0; i < files.length; i++) { // 删除返回的文件列表中的文件 File file = new File(directory, files[i]); if (!file.delete()) throw new IOException("Cannot delete " + file); // 删除异常 } } lockFactory.clearLock(IndexWriter.WRITE_LOCK_NAME); // 删除操作完成后,从锁工厂中清除锁,即释放锁 } private File directory = null; // File directory是FSDirectory类的一个成员 private int refCount; // 用于记录该目录dir被引用的计数增加1 protected FSDirectory() { }; // permit subclassing private void init(File path, LockFactory lockFactory) throws IOException { // 根据指定的file和lockFactory,调用该类Directory的init方法,进行FSDirectory的初始化初始化工作 directory = path; boolean doClearLockID = false; if (lockFactory == null) { // 锁工厂实例为null if (disableLocks) { // 如果锁不可以使用 lockFactory = NoLockFactory.getNoLockFactory(); // 调用NoLockFactory类,获取NoLockFactory实例,为当前的锁工厂实例。其实NoLockFactory是一个单态(singleton)模式的工厂类,应用中只能有一个锁实例,不需要进行同步 } else { // 如果锁可以使用,获取锁工厂类名称的字符串描述 String lockClassName = System .getProperty("org.apache.lucene.store.FSDirectoryLockFactoryClass"); if (lockClassName != null && !lockClassName.equals("")) { // 如果获取的锁工厂类名称的字符串描述不为null,而且者不为空 Class c; try { c = Class.forName(lockClassName); // 加载该锁工厂类 } catch (ClassNotFoundException e) { throw new IOException("unable to find LockClass " + lockClassName); } try { lockFactory = (LockFactory) c.newInstance(); // 获取一个锁工厂的实例 } catch (IllegalAccessException e) { throw new IOException( "IllegalAccessException when instantiating LockClass " + lockClassName); } catch (InstantiationException e) { throw new IOException( "InstantiationException when instantiating LockClass " + lockClassName); } catch (ClassCastException e) { throw new IOException("unable to cast LockClass " + lockClassName + " instance to a LockFactory"); } // 根据获取的锁工厂实例的类型来设置对文件File path加锁的方式 if (lockFactory instanceof NativeFSLockFactory) { ((NativeFSLockFactory) lockFactory).setLockDir(path); } else if (lockFactory instanceof SimpleFSLockFactory) { ((SimpleFSLockFactory) lockFactory).setLockDir(path); } } else { // 没有其他的锁工厂类可用,则使用默认的锁工厂类创建一个锁工厂实例 lockFactory = new SimpleFSLockFactory(path); doClearLockID = true; } } } setLockFactory(lockFactory); // 设置当前FSDirectory相关锁工厂实例 if (doClearLockID) { // Clear the prefix because write.lock will be // stored in our directory: lockFactory.setLockPrefix(null); } } // 返回目录文件File directory下的所有索引文件,索引文件使用文件名的字符串描述 public String[] list() { return directory.list(IndexFileNameFilter.getFilter()); } // 如果文件name存在,则返回true public boolean fileExists(String name) { File file = new File(directory, name); // 根据File directory指定的抽象路径,以及name指定的名称创建一个文件 return file.exists(); } // 获取文件name最后修改的时间 public long fileModified(String name) { File file = new File(directory, name); return file.lastModified(); } // 返回目录文件directory下名称为name的文件最后修改的时间 public static long fileModified(File directory, String name) { File file = new File(directory, name); return file.lastModified(); } // 设置文件name当前修改的时间 public void touchFile(String name) { File file = new File(directory, name); file.setLastModified(System.currentTimeMillis()); } // 获取文件name的长度 public long fileLength(String name) { File file = new File(directory, name); return file.length(); } // 删除目录文件directory下的name文件 public void deleteFile(String name) throws IOException { File file = new File(directory, name); if (!file.delete()) throw new IOException("Cannot delete " + file); } // 重新命名文件,该方法已经废弃 public synchronized void renameFile(String from, String to) throws IOException { File old = new File(directory, from); File nu = new File(directory, to); if (nu.exists()) if (!nu.delete()) throw new IOException("Cannot delete " + nu); if (!old.renameTo(nu)) { java.io.InputStream in = null; java.io.OutputStream out = null; try { in = new FileInputStream(old); out = new FileOutputStream(nu); if (buffer == null) { buffer = new byte[1024]; } int len; while ((len = in.read(buffer)) >= 0) { out.write(buffer, 0, len); } old.delete(); } catch (IOException ioe) { IOException newExc = new IOException("Cannot rename " + old + " to " + nu); newExc.initCause(ioe); throw newExc; } finally { try { if (in != null) { try { in.close(); } catch (IOException e) { throw new RuntimeException( "Cannot close input stream: " + e.toString(), e); } } } finally { if (out != null) { try { out.close(); } catch (IOException e) { throw new RuntimeException( "Cannot close output stream: " + e.toString(), e); } } } } } } // 创建一个名称为name的文件,返回一个输出流,以便对该文件进行写入操作 public IndexOutput createOutput(String name) throws IOException { File file = new File(directory, name); if (file.exists() && !file.delete()) // 如果name指定文件存在,或者没有被删除掉,抛出异常 throw new IOException("Cannot overwrite: " + file); return new FSIndexOutput(file); // 返回文件File file的一个输出流 } // 读取名称为name的文件,返回一个输出流,以便定义对读取出来的内容进行操作 public IndexInput openInput(String name) throws IOException { return new FSIndexInput(new File(directory, name)); } // 打开指定名称为name的文件,指定大小为缓冲区大小bufferSize,返回一个输入流 public IndexInput openInput(String name, int bufferSize) throws IOException { return new FSIndexInput(new File(directory, name), bufferSize); } // 一个字符缓冲区,将字节转换为十六进制 private static final char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; // 获取锁的标识ID public String getLockID() { String dirName; try { dirName = directory.getCanonicalPath(); } catch (IOException e) { throw new RuntimeException(e.toString(), e); } byte digest[]; synchronized (DIGESTER) { digest = DIGESTER.digest(dirName.getBytes()); } StringBuffer buf = new StringBuffer(); buf.append("lucene-"); for (int i = 0; i < digest.length; i++) { int b = digest[i]; buf.append(HEX_DIGITS[(b >> 4) & 0xf]); buf.append(HEX_DIGITS[b & 0xf]); } return buf.toString(); } // 关闭目录 public synchronized void close() { if (--refCount <= 0) { synchronized (DIRECTORIES) { DIRECTORIES.remove(directory); } } } public File getFile() { return directory; } /** For debug output. */ public String toString() { return this.getClass().getName() + "@" + directory; } // FSIndexInput是一个静态内部类,用于管理文件系统中的索引文件输入流 protected static class FSIndexInput extends BufferedIndexInput { private static class Descriptor extends RandomAccessFile { // 用于记录文件打开状态的boolean型变量isOpen private boolean isOpen; long position; final long length; public Descriptor(File file, String mode) throws IOException { super(file, mode); isOpen = true; length = length(); } public void close() throws IOException { if (isOpen) { isOpen = false; super.close(); } } protected void finalize() throws Throwable { try { close(); } finally { super.finalize(); } } } private final Descriptor file; boolean isClone; public FSIndexInput(File path) throws IOException { this(path, BufferedIndexInput.BUFFER_SIZE); } public FSIndexInput(File path, int bufferSize) throws IOException { super(bufferSize); file = new Descriptor(path, "r"); } // 比较底层的读取操作,主要是对字节操作 protected void readInternal(byte[] b, int offset, int len) throws IOException { synchronized (file) { long position = getFilePointer(); if (position != file.position) { file.seek(position); file.position = position; } int total = 0; do { int i = file.read(b, offset + total, len - total); if (i == -1) throw new IOException("read past EOF"); file.position += i; total += i; } while (total < len); } } public void close() throws IOException { if (!isClone) file.close(); } protected void seekInternal(long position) { } public long length() { return file.length; } public Object clone() { FSIndexInput clone = (FSIndexInput) super.clone(); clone.isClone = true; return clone; } /** Method used for testing. Returns true if the underlying * file descriptor is valid. */ boolean isFDValid() throws IOException { return file.getFD().valid(); } } // FSIndexOutput是一个静态内部类,用于管理文件系统中的索引文件输出流,与FSIndexInput实现类似 protected static class FSIndexOutput extends BufferedIndexOutput { RandomAccessFile file = null; // 用于记录文件打开状态的boolean型变量isOpen private boolean isOpen; public FSIndexOutput(File path) throws IOException { file = new RandomAccessFile(path, "rw"); isOpen = true; } // 从缓冲区写入文件的方法 public void flushBuffer(byte[] b, int offset, int size) throws IOException { file.write(b, offset, size); } public void close() throws IOException { if (isOpen) { super.close(); file.close(); isOpen = false; } } // 随机访问的方法实现 public void seek(long pos) throws IOException { super.seek(pos); file.seek(pos); } public long length() throws IOException { return file.length(); } } }
上面FSDirectory类的实现挺复杂的,主要是在继承Directory抽象类的基础上,增加了文件系统目录锁特有的一些操作方式。
通过FSDirectory类源代码的阅读,关于文件系统目录FSDirectory类,总结几点:
1、锁工厂的获取及其管理;
2、对文件系统目录下索引文件的输入流和输出流的管理;
3、获取FSDirectory类实例;
4、获取锁工厂实例后,可以创建一个新的FSDirectory类实例,在此之前先要完成一些初始化工作;
5、继承自Directory抽象类,自然可以实现索引文件的的拷贝操作。
6、FSDirectory类中实现了很多静态内部类,这使得只能在FSDirectory类内部访问这些静态类,对外部透明。
发表评论
-
Lucene学习(22)
2009-10-30 11:14 876关于FieldInfos类和FieldInfo类。 Fi ... -
Lucene学习(21)
2009-10-30 11:12 841回到IndexWriter索引器类中来,学习该类添加Docum ... -
Lucene学习(20)
2009-10-30 11:06 1008关于Field类和Document类。 ... -
Lucene学习(19)
2009-10-30 11:01 819研究SegmentInfo类的实现 ... -
Lucene学习(18)
2009-10-30 10:47 1873关于SegmentInfos类的具体 ... -
Lucene学习(17)
2009-10-30 10:40 843根据16中对IndexFileDeleter ... -
Lucene学习(16)
2009-10-30 10:33 1066在接触到索引删除的策略IndexDeletionPolicy ... -
Lucene学习(15)
2009-10-30 10:28 871关于索引删除的策略IndexDeletionPolicy 。 ... -
Lucene学习(14)
2009-10-30 10:23 754RAMDirectory类是与内存目录相关的,它和FSDire ... -
Lucene学习(12)
2009-10-30 10:17 689接着昨天学习的Lucene-2.3.1 源代码阅读学习(11) ... -
Lucene学习(11)
2009-10-30 10:06 1100对数据源进行分析,是为建立索引服务的;为指定的文件建立索引,是 ... -
Lucene学习(10)
2009-10-30 10:02 836Lucene的CJKAnalyzer分析器。 CJKAnal ... -
Lucene学习(9)
2009-10-30 09:34 914Lucene的StandardAnalyzer分析器。 ... -
Lucene学习(8)
2009-10-30 09:27 812Lucene分析器的实现。 Lucene(分词)过滤器Tok ... -
Lucene学习(7)
2009-10-30 09:22 754CharTokenizer是一个抽象类 ... -
Lucene学习(6)
2009-10-29 16:16 859Lucene分析器的实现。 Lucene分词器Tokeniz ... -
Lucene学习(5)
2009-10-29 16:13 893研究Lucene分析器的实现。 Analyzer抽象类 ... -
Lucene学习(4)
2009-10-29 16:09 879建立索引,通过已经生成的索引文件,实现通过关键字检索。 ... -
Lucene学习(3)
2009-10-29 16:06 843org.apache.lucene.demo.IndexFil ... -
Lucene学习(2)
2009-10-29 15:59 808IndexWriter是一个非常重要的工具。建立索引必须从它开 ...
相关推荐
这个"lucene3.0.3搜索的使用示例"压缩包文件很可能是为了帮助用户理解并学习如何在项目中应用Lucene 3.0.3版本的功能。 在Lucene 3.0.3中,主要包含了以下核心概念和知识点: 1. **索引(Indexing)**:这是Lucene...
1> lucene学习笔记 2> 全文检索的实现机制 【1】lucene学习笔记的目录如下 1. 概述 3 2. lucene 的包结构 3 3. 索引文件格式 3 4. lucene中主要的类 4 4.1. Document文档类 4 4.1.1. 常用方法 4 4.1.2. 示例 4 4.2...
综上所述,"开发自己的搜索引擎lucene+heritrix(第2版)"的源码涵盖了从网络数据抓取到全文检索的全过程,适合开发者深入学习和实践搜索引擎技术。通过研究ch13至ch16的源代码,可以更深入地理解这两个工具的交互和...
7. **学习资源与社区**:除了书中的内容,学习Lucene和Heritrix还可以参考Apache官方文档、Stack Overflow上的讨论、GitHub上的开源项目以及各种技术论坛。开发者社区提供了丰富的示例代码、教程和问答资源,有助于...
5. **第13章:桌面搜索引擎开发实例** - 这一章提供了一个实际的桌面搜索引擎的开发案例,通过实例教读者如何将Lucene应用到桌面搜索环境中,如何索引本地文件系统,并实现快速的文件搜索。 6. **第14章:Web搜索...
第13章“桌面搜索引擎开发实例”提供了具体的实践案例,让读者了解如何将Lucene应用于桌面环境,其中可能涉及: 1. 文件系统的索引构建:如何遍历文件系统,提取文本内容并建立索引。 2. 实时索引更新:当文件系统...
《杨中科.net13季》是一系列...通过《杨中科.net13季》的学习,学员不仅能够全面理解.NET技术体系,还能掌握实际项目开发中的最佳实践。无论是初学者还是经验丰富的开发者,都能从中受益,不断提升自己的.NET技术能力。
杨中科老师的全13季 .NET视频教程(C#)是一个深入学习.NET技术的宝贵资源,涵盖了从基础到高级的广泛主题。 C#,作为.NET框架的主要编程语言,由微软设计,旨在提高软件开发的生产力,同时保持类型安全性和面向对象...
了解并掌握常用的外部API和框架,如Log4J(日志)、Quartz(调度)、JGroups(网络组通信)、JCache(分布式缓存)、Lucene(全文检索)等。 ### 19. 跨平台与本地接口 学习跨平台开发技巧,掌握JNI(Java Native ...
2012-06-13 13:38 9,178,682 Lucene 3.0 原理与代码分析完整版.pdf 2012-06-13 13:46 10,582,426 姚晨屏保(宽屏).exe 2012-06-13 13:10 23,625,694 Visual.C.系统开发实例精粹(源代码).7z 2012-06-13 13:46 25,062,...
它基于Lucene库构建,提供了一个分布式、RESTful风格的搜索和分析引擎,能够处理海量数据并快速响应查询。 描述中的重复词汇“干干干干刚馕”可能是个玩笑或者误输入,没有提供具体的信息,但我们可以根据常见的ES...
7. **搜索引擎和工作流**:Lucene用于全文搜索,HTMLParser和Heritrix则涉及网页抓取,JBPM则是工作流程管理工具,学员将学习如何集成这些工具来提升应用功能。 8. **XML处理**:XML作为数据交换格式,学员将学习其...
当时,GitHub拥有庞大的数据量,包括13亿个文件和1300亿行代码,这些数据都需要被高效地索引和检索。GitHub使用ElasticSearch后,其搜索性能显著提升,目前的集群规模包括26个索引存储节点和8个客户端节点(负责处理...
#### 13. XML与相关API 掌握XML处理API,如JAXP、JDOM、DOM4J、JAXB、JAXM等,实现XML数据的解析和操作。 #### 14. Web服务技术 学习SOAP、REST等Web服务技术,包括JAX-RPC、SAAJ、JAX-WS等API的使用,实现跨平台的...
13. 在学习资料的开头提到的运行程序需设置JVM参数,如-Djava.security.auth.login.config==jaas.config,表明了程序在运行时可能涉及到Java安全认证和授权服务(JAAS)。 学习JackRabbit对于理解内容管理系统、...
#### 目标13:掌握XML处理API - **API选择**:JAXP、JDOM、DOM4J、JAXR等。 - **应用案例**:XML文档解析、转换及验证。 #### 目标14:学习Web服务API - **技术要点**:JAX-RPC、SAAJ、JAXB、JAXM、JAXR、JWSDP等...
- **Lucene**:学习全文检索技术的基础知识。 ### 21. 本地接口与连接器 - **JNI、JCA**:掌握Java Native Interface、Java Connector Architecture等技术,实现Java与其他语言或平台的交互。 通过以上知识点的...
#### 13. 面向切面编程与工具 熟悉面向切面编程(AOP)及其工具如AspectJ、AspectWerkz,可以帮助你更优雅地处理横切关注点。 #### 14. 日志记录与调度 了解不同日志框架如Log4J,以及任务调度工具如Quartz,可以...