2016-09-20 11 views
0

Hy, 我有一個非常大的XML文件(100GB),其中包含foo列表,我想將它轉換爲類似於他們的流到java 8的對象:如何將大型XML文件轉換爲對象的流式樣java8

任何想法的lib或代碼示例?

開頭:

<foos> 
    <foo>...</foo> 
    <foo>...</foo> 
</foos> 

末:

Stream<Foo> foosStream = ????("foo.xml") 
streamFoos.forEach(foo->foo.doFooStuffs()); 

編輯: @Pierre感謝你,這裏是你的解決方案的實施:

try { 
      XMLEventReader reader = XMLInputFactory.newInstance(). 
        createXMLEventReader(stream); 
      final Unmarshaller unmarshaller = JAXBContext.newInstance(XXXXX.class).createUnmarshaller(); 

      Iterator<XXXXX> it = new XmlIterator<>(reader, unmarshaller, "xxxxxx"); 
      return StreamSupport.stream(Spliterators.spliteratorUnknownSize(it, Spliterator.ORDERED), false); 
     } catch (XMLStreamException e1) { 
      logger.error("XMLStreamException", e1); 
     } catch (JAXBException e) { 
      logger.error("JAXBException", e); 
     } 

public class XmlIterator<T> implements Iterator<T> { 

    private final Logger logger = LoggerFactory.getLogger(this.getClass()); 

    XMLEventReader reader; 

    XMLEvent event; 

    Unmarshaller unmarshaller; 
    String name; 

    public XmlIterator(XMLEventReader reader, Unmarshaller unmarshaller, String name) { 
     this.reader = reader; 
     this.unmarshaller = unmarshaller; 
     this.name = name; 
     try { 
      reader.next(); 
      this.event = reader.peek(); 
     } catch (XMLStreamException e) { 
      logger.error("", e); 
      event = null; 
     } 
    } 

    @Override 
    public boolean hasNext() { 
     try { 
      while (event != null && !(event.isStartElement() && name.equals(event.asStartElement().getName().getLocalPart()))) { 
       Object a = reader.next(); 
       event = reader.peek(); 
      } 
      return event != null; 

     } catch (XMLStreamException e) { 
      logger.error("", e); 
      event = null; 
     } 
     return event != null; 
    } 

    @Override 
    public T next() { 
     try { 
      T next = ((JAXBElement<T>) unmarshaller.unmarshal(reader)).getValue(); 
      event = reader.peek(); 
      return next; 
     } catch (JAXBException e) { 
      logger.error("error during unmarshalling ", e); 
      return null; 
     } catch (XMLStreamException e) { 
      logger.error("error during stream ", e); 
      return null; 
     } 
    } 
} 
+1

您是否知道使用不同的技術和API讀取Java中的XML文件?你認爲哪一個適合這裏? XML文件將會有多大?可能你想看看[StAX](https://docs.oracle.com/javase/tutorial/jaxp/stax/api.html),但是你可以在你的問題中添加更多的上下文嗎? – Tunaki

+1

是的,我知道很多lib,但它們都非常低級。我不明白爲什麼在2016年我仍然必須分析手動啓動start_element以生成自己的流,只要我可以指定Xpath。 – sab

+0

「我仍然需要手動分析start_element以生成自己的流」:看看jaxb(=爲數據定義一個xml架構) – Pierre

回答

3
+0

可能更容易不使用流並自己爲每個' Foo'遇到電話... – fabian

+0

所有的lib比我發現似乎過時的流,有沒有更多的最近的lib? – sab

+0

這是否需要在解析開始之前將整個XML存儲在內存中? – Bassam