TermVectorsWriter.cs
上传用户:zhangkuixh
上传日期:2013-09-30
资源大小:5473k
文件大小:12k
源码类别:

搜索引擎

开发平台:

C#

  1. /*
  2.  * Copyright 2004 The Apache Software Foundation
  3.  * 
  4.  * Licensed under the Apache License, Version 2.0 (the "License");
  5.  * you may not use this file except in compliance with the License.
  6.  * You may obtain a copy of the License at
  7.  * 
  8.  * http://www.apache.org/licenses/LICENSE-2.0
  9.  * 
  10.  * Unless required by applicable law or agreed to in writing, software
  11.  * distributed under the License is distributed on an "AS IS" BASIS,
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13.  * See the License for the specific language governing permissions and
  14.  * limitations under the License.
  15.  */
  16. using System;
  17. using Directory = Lucene.Net.Store.Directory;
  18. using IndexOutput = Lucene.Net.Store.IndexOutput;
  19. using StringHelper = Lucene.Net.Util.StringHelper;
  20. namespace Lucene.Net.Index
  21. {
  22. /// <summary> Writer works by opening a document and then opening the fields within the document and then
  23. /// writing out the vectors for each field.
  24. /// 
  25. /// Rough usage:
  26. /// 
  27. /// <CODE>
  28. /// for each document
  29. /// {
  30. /// writer.openDocument();
  31. /// for each field on the document
  32. /// {
  33. /// writer.openField(field);
  34. /// for all of the terms
  35. /// {
  36. /// writer.addTerm(...)
  37. /// }
  38. /// writer.closeField
  39. /// }
  40. /// writer.closeDocument()    
  41. /// }
  42. /// </CODE>
  43. /// 
  44. /// </summary>
  45. /// <version>  $Id: TermVectorsWriter.java 150689 2004-11-29 21:42:02Z bmesser $
  46. /// 
  47. /// </version>
  48. sealed class TermVectorsWriter
  49. {
  50. internal const byte STORE_POSITIONS_WITH_TERMVECTOR = (byte) (0x1);
  51. internal const byte STORE_OFFSET_WITH_TERMVECTOR = (byte) (0x2);
  52. internal const int FORMAT_VERSION = 2;
  53. //The size in bytes that the FORMAT_VERSION will take up at the beginning of each file 
  54. internal const int FORMAT_SIZE = 4;
  55. internal const System.String TVX_EXTENSION = ".tvx";
  56. internal const System.String TVD_EXTENSION = ".tvd";
  57. internal const System.String TVF_EXTENSION = ".tvf";
  58. private IndexOutput tvx = null, tvd = null, tvf = null;
  59. private System.Collections.ArrayList fields = null;
  60. private System.Collections.ArrayList terms = null;
  61. private FieldInfos fieldInfos;
  62. private TVField currentField = null;
  63. private long currentDocPointer = - 1;
  64. public TermVectorsWriter(Directory directory, System.String segment, FieldInfos fieldInfos)
  65. {
  66. // Open files for TermVector storage
  67. tvx = directory.CreateOutput(segment + TVX_EXTENSION);
  68. tvx.WriteInt(FORMAT_VERSION);
  69. tvd = directory.CreateOutput(segment + TVD_EXTENSION);
  70. tvd.WriteInt(FORMAT_VERSION);
  71. tvf = directory.CreateOutput(segment + TVF_EXTENSION);
  72. tvf.WriteInt(FORMAT_VERSION);
  73. this.fieldInfos = fieldInfos;
  74. fields = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(fieldInfos.Size()));
  75. terms = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(10));
  76. }
  77. public void  OpenDocument()
  78. {
  79. CloseDocument();
  80. currentDocPointer = tvd.GetFilePointer();
  81. }
  82. public void  CloseDocument()
  83. {
  84. if (IsDocumentOpen())
  85. {
  86. CloseField();
  87. WriteDoc();
  88. fields.Clear();
  89. currentDocPointer = - 1;
  90. }
  91. }
  92. public bool IsDocumentOpen()
  93. {
  94. return currentDocPointer != - 1;
  95. }
  96. /// <summary>Start processing a field. This can be followed by a number of calls to
  97. /// addTerm, and a final call to closeField to indicate the end of
  98. /// processing of this field. If a field was previously open, it is
  99. /// closed automatically.
  100. /// </summary>
  101. public void  OpenField(System.String field)
  102. {
  103. FieldInfo fieldInfo = fieldInfos.FieldInfo(field);
  104. OpenField(fieldInfo.number, fieldInfo.storePositionWithTermVector, fieldInfo.storeOffsetWithTermVector);
  105. }
  106. private void  OpenField(int fieldNumber, bool storePositionWithTermVector, bool storeOffsetWithTermVector)
  107. {
  108. if (!IsDocumentOpen())
  109. throw new System.SystemException("Cannot open field when no document is open.");
  110. CloseField();
  111. currentField = new TVField(fieldNumber, storePositionWithTermVector, storeOffsetWithTermVector);
  112. }
  113. /// <summary>Finished processing current field. This should be followed by a call to
  114. /// openField before future calls to addTerm.
  115. /// </summary>
  116. public void  CloseField()
  117. {
  118. if (IsFieldOpen())
  119. {
  120. /* DEBUG */
  121. //System.out.println("closeField()");
  122. /* DEBUG */
  123. // save field and terms
  124. WriteField();
  125. fields.Add(currentField);
  126. terms.Clear();
  127. currentField = null;
  128. }
  129. }
  130. /// <summary>Return true if a field is currently open. </summary>
  131. public bool IsFieldOpen()
  132. {
  133. return currentField != null;
  134. }
  135. /// <summary>Add term to the field's term vector. Field must already be open.
  136. /// Terms should be added in
  137. /// increasing order of terms, one call per unique termNum. ProxPointer
  138. /// is a pointer into the TermPosition file (prx). Freq is the number of
  139. /// times this term appears in this field, in this document.
  140. /// </summary>
  141. /// <throws>  IllegalStateException if document or field is not open </throws>
  142. public void  AddTerm(System.String termText, int freq)
  143. {
  144. AddTerm(termText, freq, null, null);
  145. }
  146. public void  AddTerm(System.String termText, int freq, int[] positions, TermVectorOffsetInfo[] offsets)
  147. {
  148. if (!IsDocumentOpen())
  149. throw new System.SystemException("Cannot add terms when document is not open");
  150. if (!IsFieldOpen())
  151. throw new System.SystemException("Cannot add terms when field is not open");
  152. AddTermInternal(termText, freq, positions, offsets);
  153. }
  154. private void  AddTermInternal(System.String termText, int freq, int[] positions, TermVectorOffsetInfo[] offsets)
  155. {
  156. TVTerm term = new TVTerm();
  157. term.termText = termText;
  158. term.freq = freq;
  159. term.positions = positions;
  160. term.offsets = offsets;
  161. terms.Add(term);
  162. }
  163. /// <summary> Add a complete document specified by all its term vectors. If document has no
  164. /// term vectors, add value for tvx.
  165. /// 
  166. /// </summary>
  167. /// <param name="vectors">
  168. /// </param>
  169. /// <throws>  IOException </throws>
  170. public void  AddAllDocVectors(TermFreqVector[] vectors)
  171. {
  172. OpenDocument();
  173. if (vectors != null)
  174. {
  175. for (int i = 0; i < vectors.Length; i++)
  176. {
  177. bool storePositionWithTermVector = false;
  178. bool storeOffsetWithTermVector = false;
  179. try
  180. {
  181. TermPositionVector tpVector = (TermPositionVector) vectors[i];
  182. if (tpVector.Size() > 0 && tpVector.GetTermPositions(0) != null)
  183. storePositionWithTermVector = true;
  184. if (tpVector.Size() > 0 && tpVector.GetOffsets(0) != null)
  185. storeOffsetWithTermVector = true;
  186. FieldInfo fieldInfo = fieldInfos.FieldInfo(tpVector.GetField());
  187. OpenField(fieldInfo.number, storePositionWithTermVector, storeOffsetWithTermVector);
  188. for (int j = 0; j < tpVector.Size(); j++)
  189. AddTermInternal(tpVector.GetTerms()[j], tpVector.GetTermFrequencies()[j], tpVector.GetTermPositions(j), tpVector.GetOffsets(j));
  190. CloseField();
  191. }
  192. catch (System.InvalidCastException ignore)
  193. {
  194. TermFreqVector tfVector = vectors[i];
  195. FieldInfo fieldInfo = fieldInfos.FieldInfo(tfVector.GetField());
  196. OpenField(fieldInfo.number, storePositionWithTermVector, storeOffsetWithTermVector);
  197. for (int j = 0; j < tfVector.Size(); j++)
  198. AddTermInternal(tfVector.GetTerms()[j], tfVector.GetTermFrequencies()[j], null, null);
  199. CloseField();
  200. }
  201. }
  202. }
  203. CloseDocument();
  204. }
  205. /// <summary>Close all streams. </summary>
  206. internal void  Close()
  207. {
  208. try
  209. {
  210. CloseDocument();
  211. }
  212. finally
  213. {
  214. // make an effort to close all streams we can but remember and re-throw
  215. // the first exception encountered in this process
  216. System.IO.IOException keep = null;
  217. if (tvx != null)
  218. try
  219. {
  220. tvx.Close();
  221. }
  222. catch (System.IO.IOException e)
  223. {
  224. if (keep == null)
  225. keep = e;
  226. }
  227. if (tvd != null)
  228. try
  229. {
  230. tvd.Close();
  231. }
  232. catch (System.IO.IOException e)
  233. {
  234. if (keep == null)
  235. keep = e;
  236. }
  237. if (tvf != null)
  238. try
  239. {
  240. tvf.Close();
  241. }
  242. catch (System.IO.IOException e)
  243. {
  244. if (keep == null)
  245. keep = e;
  246. }
  247. if (keep != null)
  248. {
  249. throw new System.IO.IOException(keep.StackTrace);
  250. }
  251. }
  252. }
  253. private void  WriteField()
  254. {
  255. // remember where this field is written
  256. currentField.tvfPointer = tvf.GetFilePointer();
  257. //System.out.println("Field Pointer: " + currentField.tvfPointer);
  258. int size = terms.Count;
  259. tvf.WriteVInt(size);
  260. bool storePositions = currentField.storePositions;
  261. bool storeOffsets = currentField.storeOffsets;
  262. byte bits = (byte) (0x0);
  263. if (storePositions)
  264. bits |= STORE_POSITIONS_WITH_TERMVECTOR;
  265. if (storeOffsets)
  266. bits |= STORE_OFFSET_WITH_TERMVECTOR;
  267. tvf.WriteByte(bits);
  268. System.String lastTermText = "";
  269. for (int i = 0; i < size; i++)
  270. {
  271. TVTerm term = (TVTerm) terms[i];
  272. int start = StringHelper.StringDifference(lastTermText, term.termText);
  273. int length = term.termText.Length - start;
  274. tvf.WriteVInt(start); // write shared prefix length
  275. tvf.WriteVInt(length); // write delta length
  276. tvf.WriteChars(term.termText, start, length); // write delta chars
  277. tvf.WriteVInt(term.freq);
  278. lastTermText = term.termText;
  279. if (storePositions)
  280. {
  281. if (term.positions == null)
  282. throw new System.SystemException("Trying to write positions that are null!");
  283. // use delta encoding for positions
  284. int position = 0;
  285. for (int j = 0; j < term.freq; j++)
  286. {
  287. tvf.WriteVInt(term.positions[j] - position);
  288. position = term.positions[j];
  289. }
  290. }
  291. if (storeOffsets)
  292. {
  293. if (term.offsets == null)
  294. throw new System.SystemException("Trying to write offsets that are null!");
  295. // use delta encoding for offsets
  296. int position = 0;
  297. for (int j = 0; j < term.freq; j++)
  298. {
  299. tvf.WriteVInt(term.offsets[j].GetStartOffset() - position);
  300. tvf.WriteVInt(term.offsets[j].GetEndOffset() - term.offsets[j].GetStartOffset()); //Save the diff between the two.
  301. position = term.offsets[j].GetEndOffset();
  302. }
  303. }
  304. }
  305. }
  306. private void  WriteDoc()
  307. {
  308. if (IsFieldOpen())
  309. throw new System.SystemException("Field is still open while writing document");
  310. //System.out.println("Writing doc pointer: " + currentDocPointer);
  311. // write document index record
  312. tvx.WriteLong(currentDocPointer);
  313. // write document data record
  314. int size = fields.Count;
  315. // write the number of fields
  316. tvd.WriteVInt(size);
  317. // write field numbers
  318. for (int i = 0; i < size; i++)
  319. {
  320. TVField field = (TVField) fields[i];
  321. tvd.WriteVInt(field.number);
  322. }
  323. // write field pointers
  324. long lastFieldPointer = 0;
  325. for (int i = 0; i < size; i++)
  326. {
  327. TVField field = (TVField) fields[i];
  328. tvd.WriteVLong(field.tvfPointer - lastFieldPointer);
  329. lastFieldPointer = field.tvfPointer;
  330. }
  331. //System.out.println("After writing doc pointer: " + tvx.getFilePointer());
  332. }
  333. private class TVField
  334. {
  335. internal int number;
  336. internal long tvfPointer = 0;
  337. internal bool storePositions = false;
  338. internal bool storeOffsets = false;
  339. internal TVField(int number, bool storePos, bool storeOff)
  340. {
  341. this.number = number;
  342. storePositions = storePos;
  343. storeOffsets = storeOff;
  344. }
  345. }
  346. private class TVTerm
  347. {
  348. internal System.String termText;
  349. internal int freq = 0;
  350. internal int[] positions = null;
  351. internal TermVectorOffsetInfo[] offsets = null;
  352. }
  353. }
  354. }