¿Cómo obtener un TokenStream de un Lucene TokenStream?

Intento usar Apache Lucene para tokenizar, y estoy desconcertado en el proceso para obtener Tokens de un TokenStream .

La peor parte es que estoy viendo los comentarios en los JavaDocs que abordan mi pregunta.

http://lucene.apache.org/java/3_0_1/api/core/org/apache/lucene/analysis/TokenStream.html#incrementToken%28%29

De alguna manera, se supone que se debe usar un AttributeSource , en lugar de Token s. Estoy totalmente perdido.

¿Alguien puede explicar cómo obtener información similar a un token de un TokenStream?

Sí, es un poco intrincado (comparado con el buen estilo), pero debería hacerlo:

 TokenStream tokenStream = analyzer.tokenStream(fieldName, reader); OffsetAttribute offsetAttribute = tokenStream.getAttribute(OffsetAttribute.class); TermAttribute termAttribute = tokenStream.getAttribute(TermAttribute.class); while (tokenStream.incrementToken()) { int startOffset = offsetAttribute.startOffset(); int endOffset = offsetAttribute.endOffset(); String term = termAttribute.term(); } 

Editar: La nueva forma

Según Donotello, TermAttribute ha quedado en desuso en favor de CharTermAttribute . Según jpountz (y la documentación de Lucene), addAttribute es más deseable que getAttribute .

 TokenStream tokenStream = analyzer.tokenStream(fieldName, reader); OffsetAttribute offsetAttribute = tokenStream.addAttribute(OffsetAttribute.class); CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class); tokenStream.reset(); while (tokenStream.incrementToken()) { int startOffset = offsetAttribute.startOffset(); int endOffset = offsetAttribute.endOffset(); String term = charTermAttribute.toString(); } 

Así es como debe ser (una versión limpia de la respuesta de Adán):

 TokenStream stream = analyzer.tokenStream(null, new StringReader(text)); CharTermAttribute cattr = stream.addAttribute(CharTermAttribute.class); stream.reset(); while (stream.incrementToken()) { System.out.println(cattr.toString()); } stream.end(); stream.close(); 

Hay dos variaciones en la pregunta OP:

  1. ¿Cuál es “el proceso para obtener Tokens de un TokenStream”?
  2. “¿Alguien puede explicar cómo obtener información similar a un token de un TokenStream?”

Las versiones recientes de la documentación de Lucene para Token dicen (énfasis añadido):

NOTA: A partir de 2.9 … ya no es necesario usar TokenStream, con la nueva API TokenStream se puede utilizar como clase de conveniencia que implementa todos los Atributos, lo que es especialmente útil para cambiar fácilmente de la antigua a la nueva API de TokenStream.

Y TokenStream dice que su API:

… ha pasado de estar basado en tokens a basado en atributos … la forma preferida de almacenar la información de un token es usar AttributeImpls.

Las otras respuestas a esta pregunta cubren el número 2 anterior: cómo obtener información similar a un TokenStream un TokenStream en la “nueva” forma recomendada mediante el uso de atributos. Al leer la documentación, los desarrolladores de Lucene sugieren que este cambio se realizó, en parte, para reducir el número de objetos individuales creados a la vez.

Pero como algunas personas han señalado en los comentarios de esas respuestas, no responden directamente al # 1: ¿cómo obtienes un Token si realmente quieres / necesitas ese tipo?

Con el mismo cambio de API que hace que TokenStream sea ​​un AttributeSource , Token ahora implementa Attribute y se puede usar con TokenStream.addAttribute al igual que las otras respuestas muestran para CharTermAttribute y OffsetAttribute . Entonces respondieron realmente esa parte de la pregunta original, simplemente no la mostraron.

Es importante que, si bien este enfoque le permitirá acceder a Token mientras realiza un bucle, siga siendo solo un objeto, sin importar cuántos tokens lógicos haya en la transmisión. Cada llamada a incrementToken() cambiará el estado del Token devuelto desde addAttribute ; Entonces, si su objective es construir una colección de diferentes objetos Token para usar fuera del ciclo, entonces deberá hacer un trabajo adicional para crear un nuevo objeto Token como una copia (¿profunda?).

Para la última versión de lucene 7.3.1

  // Test the tokenizer Analyzer testAnalyzer = new CJKAnalyzer(); String testText = "Test Tokenizer"; TokenStream ts = testAnalyzer.tokenStream("context", new StringReader(testText)); OffsetAttribute offsetAtt = ts.addAttribute(OffsetAttribute.class); try { ts.reset(); // Resets this stream to the beginning. (Required) while (ts.incrementToken()) { // Use AttributeSource.reflectAsString(boolean) // for token stream debugging. System.out.println("token: " + ts.reflectAsString(true)); System.out.println("token start offset: " + offsetAtt.startOffset()); System.out.println(" token end offset: " + offsetAtt.endOffset()); } ts.end(); // Perform end-of-stream operations, eg set the final offset. } finally { ts.close(); // Release resources associated with this stream. } 

Referencia: https://lucene.apache.org/core/7_3_1/core/org/apache/lucene/analysis/package-summary.html