2015-10-20 28 views
5

परिदृश्य: मुझे चरम धीमी नेटवर्क के माध्यम से एक विशाल एक्सएमएल फ़ाइल प्राप्त हो रही है, इसलिए मैं जितनी जल्दी हो सके अत्यधिक प्रसंस्करण शुरू करना चाहता हूं। इसके कारण मैंने SAXParser का उपयोग करने का निर्णय लिया।एसएक्सपार्स घटनाओं को फेंकने से पहले इतना क्यों पढ़ता है?

मुझे उम्मीद थी कि एक टैग समाप्त होने के बाद मुझे एक कार्यक्रम मिलेगा।

निम्न परीक्षण से पता चलता है कि मैं क्या मतलब है:

@Test 
public void sax_parser_read_much_things_before_returning_events() throws Exception{ 
    String xml = "<a>" 
       + " <b>..</b>" 
       + " <c>..</c>" 
        // much more ... 
       + "</a>"; 

    // wrapper to show what is read 
    InputStream is = new InputStream() { 
     InputStream is = new ByteArrayInputStream(xml.getBytes()); 

     @Override 
     public int read() throws IOException { 
      int val = is.read(); 
      System.out.print((char) val); 
      return val; 
     } 
    }; 

    SAXParser parser = SAXParserFactory.newInstance().newSAXParser(); 
    parser.parse(is, new DefaultHandler(){ 
     @Override 
     public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { 
      System.out.print("\nHandler start: " + qName); 
     } 

     @Override 
     public void endElement(String uri, String localName, String qName) throws SAXException { 
      System.out.print("\nHandler end: " + qName); 
     } 
    }); 
} 

मैं इनपुट धारा लिपटे देखने के लिए क्या पढ़ा जाता है और ईवेंट होने।

मैं क्या उम्मीद कुछ इस तरह था:

<a>     <- output from read() 
Handler start: a 
<b>     <- output from read() 
Handler start: b 
</b>     <- output from read() 
Handler end: b 
... 

दुर्भाग्य से परिणाम पीछा कर रहा था:

<a> <b>..</b> <c>..</c></a>  <- output from read() 
Handler start: a 
Handler start: b 
Handler end: b 
Handler start: c 
Handler end: c 
Handler end: a 

कहां है मेरी गलती है और कैसे मैं अपेक्षित परिणाम मिल सकता है?

संपादित करें:

  • पहली बात यह है कि वह दस्तावेज़ संस्करण है, जो सब कुछ स्कैन करने के लिए कारण बनता है पता लगाने के लिए कोशिश कर रहा है है। डॉक्टर संस्करण के साथ वह (लेकिन जहां मैं उम्मीद करता हूं)
  • यह ठीक नहीं है कि वह उदाहरण के लिए 1000 बाइट्स और ब्लॉक के लिए "चाहता है" पढ़ना चाहता है क्योंकि यह संभव है कि धारा में इस पर इतना अधिक न हो इस समय पर।
  • मैं XMLEntityManager में बफर आकार नहीं मिले:
    • सार्वजनिक स्थिर अंतिम पूर्णांक DEFAULT_BUFFER_SIZE = 8192;
    • सार्वजनिक स्थिर अंतिम int DEFAULT_XMLDECL_BUFFER_SIZE = 64;
    • सार्वजनिक स्थिर अंतिम int DEFAULT_INTERNAL_BUFFER_SIZE = 1024;
+1

मुझे लगता है कि आपको एक बगजर परीक्षण फ़ाइल आज़माएं - मुझे संदेह है कि एक बफर्ड रीड प्रभावी रूप से प्रसंस्करण शुरू करने से पहले आपकी पूरी फाइल को प्रभावी ढंग से पढ़ रहा है क्योंकि यह फ़ाइल को (कहें) 1k भाग या जो कुछ भी बफर करेगा - अगर आप एक बड़ी फाइल का उपयोग करते हैं आप अपेक्षा करते हैं कि आप कुछ और प्राप्त कर सकते हैं। – Elemental

उत्तर

2

कि पदव्याख्यायित्र, इनपुट से एक हिस्सा पढ़ता है और उसके बाद वह हिस्सा प्रक्रियाओं, SAX घटनाओं जारी करने, और इतने पर है ... ऐसा लगता है आप के बारे में कैसे गलत मान्यताओं बना रहे हैं मैं/ओ काम करता है। अधिकांश सॉफ़्टवेयर की तरह एक एक्सएमएल पार्सर, डेटा में डेटा का अनुरोध करेगा, क्योंकि स्ट्रीम से एकल बाइट्स का अनुरोध प्रदर्शन आपदा के लिए एक नुस्खा है।

यह इस बात का तात्पर्य नहीं है कि बफर को पढ़ने के प्रयासों से पहले पूरी तरह से भरा जाना चाहिए। यह सिर्फ है कि ByteArrayInputStream नेटवर्क InputStream के व्यवहार को अनुकरण करने में असमर्थ है। आप आसानी से read(byte[], int, int) ओवरराइड करके और एक पूर्ण बफर वापस नहीं कर सकते हैं, लेकिन उदा।हर अनुरोध पर एक एकल बाइट:

@Test 
public void sax_parser_read_much_things_before_returning_events() throws Exception{ 
    final String xml = "<a>" 
       + " <b>..</b>" 
       + " <c>..</c>" 
        // much more ... 
       + "</a>"; 

    // wrapper to show what is read 
    InputStream is = new InputStream() { 
     InputStream is = new ByteArrayInputStream(xml.getBytes()); 

     @Override 
     public int read() throws IOException { 
      int val = is.read(); 
      System.out.print((char) val); 
      return val; 
     } 
     @Override 
     public int read(byte[] b, int off, int len) throws IOException { 
      return super.read(b, off, 1); 
     } 
    }; 

    SAXParser parser = SAXParserFactory.newInstance().newSAXParser(); 
    parser.parse(is, new DefaultHandler(){ 
     @Override 
     public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { 
      System.out.print("\nHandler start: " + qName); 
     } 

     @Override 
     public void endElement(String uri, String localName, String qName) throws SAXException { 
      System.out.print("\nHandler end: " + qName); 
     } 
    }); 
} 

यह

<a> 
Handler start: a<b> 
Handler start: b..</b> 
Handler end: b <c> 
Handler start: c..</c> 
Handler end: c</a> 
Handler end: a? 

दिखा प्रिंट होगा, कैसे XML पार्सर InputStream से डेटा की उपलब्धता के लिए adapts।

+2

'पढ़ा गया (बाइट [], int, int) 'को वापसी' super.read (b, off, 1) के रूप में सरलीकृत किया जा सकता है;'। –

+0

@ डिडिएर एल: वास्तव में, अच्छी पकड़। – Holger

1

आंतरिक SAX पार्सर सबसे शायद या एक BufferedReader में अपने InputStream लिपटे बफरिंग के कुछ प्रकार का उपयोग करता है। अन्यथा यह इनपुट से एकल बाइट पढ़ेगा जो वास्तव में प्रदर्शन को नुकसान पहुंचाएगा।

तो क्या आप देख रहे हैं

संबंधित मुद्दे