2010-08-19 190 views
2

我继承了一个使用简单文本文件保存文档的数据存储。加载XML非常慢

文档具有一些属性(日期,标题和文本),并且这些文件以文件名进行编码:< date> - < title> .txt,文件正文为文本。

然而实际上系统中的文档有更多的属性,甚至更多的是建议添加。

切换到XML格式似乎是合乎逻辑的,我已经这样做了,每个文档现在都编码在它自己的XML文件中。

但是,从XML读取文件现在很慢! (其中.txt格式的2000篇文章花费了几秒钟,现在2000篇.xml格式的文章花费了10分钟以上)。

我正在使用DOM解析器,并且在我发现读取速度有多慢之后,我切换到了SAX解析器,但它仍然一样慢(好,更快,但仍然10分钟)。

XML是否慢,还是我做一些奇怪的事情?任何想法将不胜感激。

该系统是用JavaSE 1.6编写的。 解析器创建这样的:

 

/* 
import javax.xml.parsers.ParserConfigurationException; 
import javax.xml.parsers.SAXParser; 
import javax.xml.parsers.SAXParserFactory; 
*/ 
    SAXParserFactory factory = SAXParserFactory.newInstance(); 
    SAXParser saxParser; 
    try { 
    saxParser = factory.newSAXParser(); 
    ArticleSaxHandler handler = new ArticleSaxHandler(); 
    saxParser.parse(is, handler); 
    return handler.getArticle(); 
    } catch (ParserConfigurationException e) { 
    throw new IOException(e); 
    } catch (SAXException e) { 
    throw new IOException(e); 
    } finally { 
    if (is != null) { 
     try { 
     is.close(); 
     } catch (IOException e) { 
     logger.error(e); 
     } 
    } 
    } 
} 

private class ArticleSaxHandler extends DefaultHandler { 
     private URI uri = null; 
     private String source = null; 
     private String author = null; 
     private DateTime articleDatetime = null; 
     private DateTime processedDatetime = null; 
     private String title = null; 
     private String text = null; 
     private ArticleElement currentElement; 
     private final StringBuilder builder = new StringBuilder(); 

     public Article getArticle() { 
      return new Article(uri, source, author, articleDatetime, processedDatetime, title, text); 
     } 

     /** Receive notification of the start of an element. */ 
     public void startElement(String uri, String localName, String qName, Attributes attributes) { 
      if (builder.length() != 0) { 
       throw new RuntimeException(new SAXParseException(currentElement + " was not finished before " + qName + " was started", null)); 
      } 
      currentElement = ArticleElement.getElement(qName); 
     } 

     public void endElement(String uri, String localName, String qName) { 
      final String elementText = builder.toString(); 
      builder.delete(0, builder.length()); 
      if (currentElement == null) { 
       return; 
      } 
      switch (currentElement) { 
       case ARTICLE: 
        break; 
       case URI: 
        try { 
         this.uri = new URI(elementText); 
        } catch (URISyntaxException e) { 
         throw new RuntimeException(e); 
        } 
        break; 
       case SOURCE: 
        source = elementText; 
        break; 
       case AUTHOR: 
        author = elementText; 
        break; 
       case ARTICLE_DATE_TIME: 
        articleDatetime = getDateTimeFormatter().parseDateTime(elementText); 
        break; 
       case PROCESSED_DATE_TIME: 
        processedDatetime = getDateTimeFormatter().parseDateTime(elementText); 
        break; 
       case TITLE: 
        title = elementText; 
        break; 
       case TEXT: 
        this.text = elementText; 
        break; 
       default: 
        throw new IllegalStateException("Unexpected ArticleElement: " + currentElement); 
      } 
      currentElement = null; 
     } 

     /** Receive notification of character data inside an element. */ 
     public void characters(char[] ch, int start, int length) { 
      builder.append(ch, start, length); 
     } 

     public void error(SAXParseException e) { 
      fatalError(e); 
     } 

     public void fatalError(SAXParseException e) { 
      logger.error("currentElement: " + currentElement + " ||builder: " + builder.toString() + "\n\n" + e.getMessage(), e); 
     } 
    } 

    private enum ArticleElement { 
     ARTICLE(ARTICLE_ELEMENT_NAME), URI(URI_ELEMENT_NAME), SOURCE(SOURCE_ELEMENT_NAME), AUTHOR(AUTHOR_ELEMENT_NAME), ARTICLE_DATE_TIME(
       ARTICLE_DATETIME_ELEMENT_NAME), PROCESSED_DATE_TIME(PROCESSED_DATETIME_ELEMENT_NAME), TITLE(TITLE_ELEMENT_NAME), TEXT(TEXT_ELEMENT_NAME); 
     private String name; 

     private ArticleElement(String name) { 
      this.name = name; 
     } 

     public static ArticleElement getElement(String qName) { 
      for (ArticleElement element : ArticleElement.values()) { 
       if (element.name.equals(qName)) { 
        return element; 
       } 
      } 
      return null; 
     } 
    } 
 
+0

没有XML是不是慢,本身。抓住一个分析器,并检查哪部分是缓慢的。 – 2010-08-19 11:04:40

+2

除非您发布代码示例 – 2010-08-19 11:04:43

+0

2000年的文章文件有多大,否则无法知道您是否在“做一些奇怪的事情”?你有多少内存给你的虚拟机?什么是CPU使用率? – 2010-08-19 11:06:34

回答

6

读取数据从一个缓冲流可以解释这些性能问题。这与从文本到XML的更改没有直接关系,但可能偶尔您的新实现不再使用BufferedInputStream


Follwing这条道路,详细,检查该is缓冲:

saxParser.parse(is, handler); 
+0

我认为这一定是它 - 我实际上并没有遵循这条路径,只是简单地改了一行:saxParser.parse(is,handler); to saxParser.parse(new BufferedInputStream(is),handler); 现在大约10到40毫秒每篇文章(或2000英寸〜16秒) – barryred 2010-08-19 12:26:25