Как стать автором
Обновить

Конвертирование файлов в plain text c помощью Aperture Framework

Недавно на Хабре пролетала статься PDF / DOC to TXT как получить текст из DOC или PDF файла.
Я хочу предложить свой способ конвертирования различных файлов в plain text. Это использование Aperture Framework.
Давайте сначала вкратце рассмотрим его плюсы:
  • Pure Java. А значит кроссплатформенность и независимость от установленных компонент
  • Open Source. Продукт бесплатный и развивается сообществом. А при необходимости вы можете внести изменения сами.
  • Большой набор поддерживаемых форматов: Plain text, HTML, XHTML, XML, PDF, RTF, Microsoft Office (Word, Excel, Powerpoint, Visio, Publisher), Microsoft Works, OpenOffice 1.x (Writer, Calc, Impress, Draw), StarOffice 6.x — 7.x+ (Writer, Calc, Impress, Draw), OpenDocument (OpenOffice 2.x, StarOffice 8.x), Corel WordPerfect, Quattro, Presentations, Emails (.eml files), ical files
  • Распознавание типа файла по его содержимому
  • Кроме текста фреймфорк умеет извлекать из файлов мета-данные: автора, даты создания и модификации и т.д.


Давайте посмотрим как это работает. Вот пример класса для конвертирования файлов:
package ru.me.aperture;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Set;

import org.apache.commons.io.IOUtils;
import org.semanticdesktop.aperture.extractor.Extractor;
import org.semanticdesktop.aperture.extractor.ExtractorException;
import org.semanticdesktop.aperture.extractor.ExtractorFactory;
import org.semanticdesktop.aperture.extractor.ExtractorRegistry;
import org.semanticdesktop.aperture.extractor.impl.DefaultExtractorRegistry;
import org.semanticdesktop.aperture.mime.identifier.MimeTypeIdentifier;
import org.semanticdesktop.aperture.mime.identifier.magic.MagicMimeTypeIdentifier;
import org.semanticdesktop.aperture.rdf.RDFContainer;
import org.semanticdesktop.aperture.rdf.impl.RDFContainerFactoryImpl;
import org.semanticdesktop.aperture.util.IOUtil;
import org.semanticdesktop.aperture.vocabulary.NIE;

public class FileConverter {
  private MimeTypeIdentifier mimeTypeIdentifier = new MagicMimeTypeIdentifier();
  private ExtractorRegistry extractorRegistry = new DefaultExtractorRegistry();
  
  public RDFContainer convert(File file) throws IOException, ExtractorException {

    InputStream inputStream = null;
    BufferedInputStream bufferedInputStream = null;
    
    try {
      
      inputStream = new FileInputStream(file);

      // Определяем минимальное необходимое количество байт для определения типа файла
      int minimumArrayLength = mimeTypeIdentifier.getMinArrayLength();
      int bufferSize = Math.max(minimumArrayLength, 8192);
      
      // Создаем буфер, чтобы не читать файл 2 раза
      bufferedInputStream = new BufferedInputStream(inputStream, bufferSize);
      bufferedInputStream.mark(minimumArrayLength + 10);
      
      // Читаем minimumArrayLength байт
      byte[] bytes = IOUtil.readBytes(bufferedInputStream, minimumArrayLength);

      // Определяем тип файла
      String mimeType = mimeTypeIdentifier.identify(bytes, file.getPath(), null);
      if (mimeType == null) {
        throw new ExtractorException("Can't determine mime type for " + file.getAbsolutePath());
      }
      
      // Создаем RFD-контейнер
      RDFContainerFactoryImpl containerFactory = new RDFContainerFactoryImpl();
      RDFContainer container = containerFactory.newInstance(file.toURI().toString());

      // Получаем список extractor'ов, которые могут работать с данным типом файлов
      Set<ExtractorFactory> factories = extractorRegistry.getFileExtractorFactories(mimeType);
      if (factories != null && !factories.isEmpty()) {

        // Если такие extractor'ы есть, берем первый подходящий
        ExtractorFactory factory = factories.iterator().next();
        Extractor extractor = factory.get();

        // Сбрасываем буфер, чтобы начать читать файл сначала
        bufferedInputStream.reset();
        
        // Конвертируем содержимое файла в RDF-модель
        extractor.extract(container.getDescribedUri(), bufferedInputStream, null, mimeType, container);
      }

      // Добавляем к модели MimeType
      container.add(NIE.mimeType, mimeType);
      
      return container;
    }
    finally {
      IOUtils.closeQuietly(bufferedInputStream);
      IOUtils.closeQuietly(inputStream);
    }
  }
}

* This source code was highlighted with Source Code Highlighter.

После этого конвертирование файла в текст превращается в тривиальное действие:
RDFContainer rdfContainer = fileConverter.convert(file);
System.out.println("Plain text: " + rdfContainer.getString(NIE.plainTextContent));
rdfContainer.dispose();

* This source code was highlighted with Source Code Highlighter.

Другим плюсом решения является наличие Crawler'ов, на тот случай, если перед конвертированием файлов вам необходимо их собрать с файловой системы, веба или почты.
_________
Текст подготовлен в
ХабраРедакторе
Теги:
Хабы:
Данная статья не подлежит комментированию, поскольку её автор ещё не является полноправным участником сообщества. Вы сможете связаться с автором только после того, как он получит приглашение от кого-либо из участников сообщества. До этого момента его username будет скрыт псевдонимом.