`
cfan_haifeng
  • 浏览: 122126 次
  • 性别: Icon_minigender_1
  • 来自: 郑州
社区版块
存档分类
最新评论

lucene-segments的文件格式分析

 
阅读更多

Lucene的索引文件格式(2)这篇文章写的非常好,参考他写了解析segments.gen和segments_1的代码。

代码如下(lucene版本为:lucene-core-3.4.0.jar)

 

 

package format;

import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.IndexFileNames;
import org.apache.lucene.index.SegmentInfos;
import org.apache.lucene.store.ChecksumIndexInput;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.store.IndexInput;

import constant.Constant;

/**
 * 读取segments.gen,segments_1中的信息
 * 参考:http://www.cnblogs.com/forfuture1978/archive/2009/12/14/1623599.html 索引文件格式分析
 */
public class SegmentFormatAnalysis {

	private SegmentFormatAnalysis() {
	}

	/**
	 * Index all text files under a directory.
	 * 
	 * @throws IOException
	 */
	public static void main(String[] args) throws IOException {
		getSEGMENTS_GEN();
		// 打开索引文件夹
		Runtime.getRuntime().exec("cmd.exe /c start " + Constant.INDEX_PATH);

	}

	private static void readSegmentInfo(IndexInput input, int format)
			throws IOException {
		System.out.println("version:" + input.readString());
		String name = input.readString();
		System.out.println("SegName(段名):" + name);
		int docCount = input.readInt();
		System.out.println("SegSize(此段中包含的文档数):" + docCount);

		/****/
		System.out.println("format <= SegmentInfos.FORMAT_LOCKLESS:"
				+ (format <= SegmentInfos.FORMAT_LOCKLESS));
		if (format <= SegmentInfos.FORMAT_LOCKLESS) {
			long delGen = input.readLong();
			System.out.println("delGen :" + delGen);
		} else {
			System.err.println("format 有误");
			System.exit(-1);
		}// end o if else
		/****/

		/****/
		int docStoreOffset;
		String docStoreSegment;
		boolean docStoreIsCompoundFile;
		if (format <= SegmentInfos.FORMAT_SHARED_DOC_STORE) {
			docStoreOffset = input.readInt();
			if (docStoreOffset != -1) {
				docStoreSegment = input.readString();
				docStoreIsCompoundFile = (1 == input.readByte());
			} else {
				docStoreSegment = name;
				docStoreIsCompoundFile = false;
			}
		} else {
			docStoreOffset = -1;
			docStoreSegment = name;
			docStoreIsCompoundFile = false;
		}
		System.out
				.println("docStoreOffset(如果DocStoreOffset为-1,则此段单独存储自己的域(Stored Field)和词向量(Term Vector)) :"
						+ docStoreOffset);
		System.out.println("docStoreSegment (docStoreSegment是域和词向量信息存储的段):"
				+ docStoreSegment);
		System.out.println("docStoreIsCompoundFile :" + docStoreIsCompoundFile);
		/****/

		/****/
		boolean hasSingleNormFile;
		if (format <= SegmentInfos.FORMAT_SINGLE_NORM_FILE) {
			hasSingleNormFile = (1 == input.readByte());
		} else {
			hasSingleNormFile = false;
		}
		System.out.println("hasSingleNormFile :" + hasSingleNormFile);
		/****/

		/****/
		int numNormGen = input.readInt();
		System.out.println("numNormGen :" + numNormGen);
		/****/

		byte isCompoundFile = input.readByte();
		System.out.println("isCompoundFile :" + isCompoundFile);
		int delCount;
		if (format <= SegmentInfos.FORMAT_DEL_COUNT) {
			delCount = input.readInt();
			assert delCount <= docCount;
		} else
			delCount = -1;

		System.out.println("delCount :" + delCount);

		boolean hasProx;
		if (format <= SegmentInfos.FORMAT_HAS_PROX)
			hasProx = input.readByte() == 1;
		else
			hasProx = true;

		System.out.println("hasProx :" + hasProx);

		Map<String, String> diagnostics;
		if (format <= SegmentInfos.FORMAT_DIAGNOSTICS) {
			diagnostics = input.readStringStringMap();
		} else {
			diagnostics = Collections.<String, String> emptyMap();
		}

		//

		if (format <= SegmentInfos.FORMAT_HAS_VECTORS) {
			boolean hasVectors = input.readByte() == 1;
			System.out.println("hasVectors :" + hasVectors);
		} else {
			System.err.println("format 有误");
			System.exit(-1);
		}
	}// end of method

	/**
	 * 读取segments_0,segments_1信息
	 * 
	 * @param segmentFileName
	 * @throws IOException
	 */
	private static void getSEGMENTS_N(String segmentFileName)
			throws IOException {
		System.out.println("---------------------------");
		String indexPath = Constant.INDEX_PATH;
		Directory directory = FSDirectory.open(new File(indexPath));
		// String segmentFileName = "segments_1";
		ChecksumIndexInput input = new ChecksumIndexInput(directory
				.openInput(segmentFileName));
		// Lucene 2.1此值-3,Lucene 2.9时,此值为-9。
		int format = input.readInt();
		System.out.println("Format:" + format);
		System.out.println("Version(估计其实存储的时索引最后修改的时间毫秒数):" + input.readLong());
		// System.out.println("Version:" + System.currentTimeMillis());

		// 是下一个新段(Segment)的段名。
		// 所有属于同一个段的索引文件都以段名作为文件名,一般为_0.xxx, _0.yyy, _1.xxx, _1.yyy ……
		// 新生成的段的段名一般为原有最大段名加一。
		// 如同的索引,NameCount读出来是2,说明新的段为_2.xxx, _2.yyy
		System.out.println("NameCount:" + input.readInt());

		int segCount = input.readInt();
		System.out.println("SegCount(Segment的个数):" + segCount);
		for (int i = segCount; i > 0; i--) {
			System.out.println("第" + i + "段信息 begin+++++++++++");
			readSegmentInfo(input, format);
			System.out.println("第" + i + "段信息 end +++++++++++");
			// SegmentInfo si = new SegmentInfo(directory, format, input);
		}// end of for
		//		

		if (format >= 0) { // in old format the version number may be at the end
			long version = -250;
			if (input.getFilePointer() >= input.length())
				version = System.currentTimeMillis(); // old file format without
			else
				version = input.readLong(); // read version

			System.out.println("version:" + version);
		}

		// 保存了用户从字符串到字符串的映射Map
		Map<String, String> userData;
		if (format <= SegmentInfos.FORMAT_USER_DATA) {
			if (format <= SegmentInfos.FORMAT_DIAGNOSTICS) {
				userData = input.readStringStringMap();
			} else if (0 != input.readByte()) {
				userData = Collections.singletonMap("userData", input
						.readString());
			} else {
				userData = Collections.<String, String> emptyMap();
			}
		} else {
			userData = Collections.<String, String> emptyMap();
		}
		// 遍历map-userData
		System.out.println("遍历userData:");
		Set<Map.Entry<String, String>> set = userData.entrySet();
		for (Iterator<Map.Entry<String, String>> it = set.iterator(); it
				.hasNext();) {
			Map.Entry<String, String> entry = (Map.Entry<String, String>) it
					.next();
			System.out.println(entry.getKey() + "--->" + entry.getValue());
		}// end of for

		if (format <= SegmentInfos.FORMAT_CHECKSUM) {
			final long checksumNow = input.getChecksum();
			final long checksumThen = input.readLong();
			System.out.println("checksumNow:" + checksumNow + "\tchecksumThen:"
					+ checksumThen);
			if (checksumNow != checksumThen)
				throw new CorruptIndexException(
						"checksum mismatch in segments file");
		}

		input.close();

	}// end of method

	/**
	 * 获取segments.gen中的信息
	 * 
	 * @throws IOException
	 */
	public static void getSEGMENTS_GEN() throws IOException {
		String indexPath = Constant.INDEX_PATH;
		Directory dir = FSDirectory.open(new File(indexPath));

		IndexInput genInput = dir.openInput(IndexFileNames.SEGMENTS_GEN);// "segments.gen"

		int version = genInput.readInt();// 读出版本号

		// Lucene 2.1此值-3,Lucene 2.9时,此值为-9。
		System.out.println("version:" + version);
		if (version == SegmentInfos.FORMAT_LOCKLESS) {// 如果版本号正确
			long gen0 = genInput.readLong();// 读出第一个N
			long gen1 = genInput.readLong();// 读出第二个N
			System.out.println("gen0:" + gen0 + "\tgen1:" + gen1);

			long gen = gen1;

			String segmentFileName = IndexFileNames.SEGMENTS + "_" + gen;
			System.out.println("*************************" + segmentFileName
					+ "分析结果为:" + "*************************");
			getSEGMENTS_N(segmentFileName);

			// if (gen0 == gen1) {//如果两者相等则为genB
			// genB = gen0;
			// }
		} else {
			System.out.println("version错误:" + version);
			System.exit(-1);
		}
	}

}
 

 

………………

 

分享到:
评论
1 楼 chris开到荼縻 2013-07-13  
有没有打包的代码啊?好长啊

相关推荐

    lucene-codecs-4.4.0.zip

    在IT领域,Lucene是一个非常重要的开源全文搜索引擎库,它为开发者提供了强大的文本分析、索引和搜索功能。这里我们关注的是Lucene的4.4.0版本,通过解压"lucene-codecs-4.4.0.zip",我们可以深入了解其内部机制和...

    lucene-3.3.0-src.zip

    - **复合段(Compound Segments)**: 3.3.0版本引入了复合段,将多个段合并到一个物理文件中,减少了磁盘I/O,提高了搜索速度。 - **多线程支持(Multi-threaded Support)**: 在3.3.0版本中,Lucene增强了对多...

    lucene索引文件格式介绍

    索引文件格式是Lucene实现快速搜索的关键。以下是对Lucene索引文件格式的详细说明。 首先,我们要理解Lucene索引的基本结构。一个Lucene索引位于一个文件夹中,这个文件夹包含了多个段(Segment)。每个段是独立的...

    基于JAVA的搜索引擎 lucene-2.2.0

    对数据源分析,使用Lucene的分析器(Analyzer),根据分析器所得到的词条,构造一个索引器IndexWriter。索引器IndexWriter的功能主要就是创建索引,是建立索引工作中最核心的。 当构造完一个索引器IndexWriter之后,...

    Lucene索引文件格式

    《Lucene索引文件格式详解》 Lucene,作为一款强大的全文搜索引擎库,其索引文件格式是实现高效搜索的关键。本文将深入解析Lucene 1.3版本的索引文件结构,帮助读者理解其内部运作机制。 首先,我们要理解Lucene...

    Lucene读取索引文件

    一个Lucene索引是由多个文件组成的,包括但不限于 segments文件、.del文件(删除文档标记)、.tii和.tis文件(Term Info Index和Term Info postings)、.frx、.fdx、.fdt、.fdt(Field Data)等。这些文件共同构成了...

    深入了解Lucene之一 系统结构分析.pptx

    Lucene的索引文件主要由以下部分组成: - **倒排索引(Inverted Index)**:记录了每个项在哪些文档中出现,以及对应的频率和位置信息。 - **字段长度表(Field Lengths)**:存储每个文档中各个字段的总字符数。 -...

    Lucene_原理与代码分析完整版

    Lucene索引文件的格式是其高效性和可扩展性的关键所在,主要包括以下几种类型的文件: - **段元数据文件**(segments_N):存储每个段的基本信息。 - **字段元数据文件**(.fnm):描述文档中的各个字段。 - **字段...

    lucene 原理与代码分析

    Lucene使用特定的文件格式存储索引信息,包括正向信息(如文档元数据)、反向信息(如词典和文档频率信息)和其他辅助信息。例如,`segments_N`文件存储了当前索引的段信息,`.fnm`和`.fdt`文件分别存储字段的元数据...

    Lucene-7.5.0:Lucene 7.5.0 8.4.0 8.6.0 8.7.0 8.8.0

    3. 索引文件之segments_N 4. 索引文件之fnm 5. 索引文件之si 6. 索引文件之fdx&&fdt 7. 索引文件之tvx&&tvd 8. 索引文件之liv 9. 索引文件之dim&&dii 10. 索引文件之tim&&tip 11. 索引文件之doc 12. 索引文件之pos&&...

    c# Lucene.net 原理 代码分析加强版

    《C# Lucene.net原理与代码分析加强版》是一份深度解析Lucene.net搜索引擎库的文档,涵盖了全文检索的基本原理、Lucene的总体架构、索引文件格式以及索引过程和段合并等核心主题,旨在为开发人员提供深入理解Lucene...

    Lucene中文件格式介绍

    以下是对Lucene文件格式的详细解析。 1. **Segment和Index Files** Lucene的索引被划分为多个段(Segments),每个段是一个独立的搜索单元。段是由一系列文件组成的,包括文档数据、倒排索引、字段信息等。这些...

    lucene专业名称分析概述

    Lucene还支持复合索引文件格式(.cfs),这是一种优化文件管理的方式。当useCompoundFile属性设置为True时,所有的索引字段、Term频率和位置信息都会被合并到一个单一的.cfs文件中,减少了打开大量小文件带来的性能...

    Lucene 原理与代码分析完整版.pdf

    了解Lucene索引文件的具体格式对于深入理解其内部机制至关重要。Lucene的索引文件格式包括: - **正向信息**:存储文档本身的元数据信息。 - **反向信息**:存储词项及其出现频率、位置等信息。 - **其他信息**:如...

    Annotated Lucene 中文版 Lucene源码剖析

    - **Segments文件**:记录了当前索引中的所有片段信息,包括每个片段的状态、大小等。 - **Lock文件**:用于协调多线程或分布式环境下的并发访问。 - **Deletable文件**:标记已经被删除但尚未物理删除的文档。 ...

    lucene搜索引擎项目

    索引创建通常涉及读取源数据(如文件或数据库),对数据进行分析,然后将分析结果存储到内存中的索引结构中。`db_search_Log.LDF`和`db_search_Data.MDF`可能是数据库日志和数据文件,它们可能被用作Lucene索引的...

    lucene入门指南

    1. **创建索引(Creating an Index)**: 首先,需要读取数据源(如文件或数据库),对每条记录创建一个 Lucene 文档,并添加到索引中。 2. **分析(Analysis)**: 对文档的每个字段进行分析,将文本转换为一系列的...

Global site tag (gtag.js) - Google Analytics