2008-12-10 5 views
18

में बहुत बड़ी XML दस्तावेज़ों पार्स (और थोड़ा अधिक) (निम्न में से सभी जावा में लिखा जा रहा है)जावा

मैं एक आवेदन है कि संभावित इनपुट XML दस्तावेज़ों हैं कि के रूप में ले जाएगा, निर्माण करने के लिए है, बहुत बड़ा। दस्तावेज़ एन्क्रिप्ट किया गया है - एक्सएमएलसीईसी के साथ नहीं, लेकिन मेरे क्लाइंट के पूर्ववर्ती एन्क्रिप्शन एल्गोरिदम के साथ - तीन चरणों में संसाधित किया जाएगा:

सबसे पहले, स्ट्रीम उपर्युक्त एल्गोरिदम के अनुसार डिक्रिप्ट की जाएगी।

दूसरा, एक एक्सटेंशन क्लास (जिसे मैं प्रदान कर रहा हूं एपीआई को किसी तीसरे पक्ष द्वारा लिखित) फ़ाइल के कुछ हिस्से को पढ़ेगा। जो राशि पढ़ी जाती है वह अनुमानित नहीं है - विशेष रूप से यह फ़ाइल के शीर्षलेख में होने की गारंटी नहीं है, लेकिन एक्सएमएल में किसी भी बिंदु पर हो सकती है।

आखिरकार, एक और एक्सटेंशन क्लास (एक ही सौदा) इनपुट एक्सएमएल को 1..एन सबसेट दस्तावेजों में विभाजित कर देगा। यह संभव है कि कुछ हिस्सों में दूसरे ऑपरेशन द्वारा निपटाए गए दस्तावेज के हिस्से को ओवरलैप किया जाए, यानी: मेरा मानना ​​है कि मुझे इस ऑब्जेक्ट से निपटने के लिए उपयोग की जाने वाली किसी भी तंत्र को रिवाइंड करने की आवश्यकता होगी।

वहाँ कभी एक समय में मेमोरी में डेटा के पूरे टुकड़ा पढ़ने के बिना यह करने के लिए एक रास्ता है:

यहाँ मेरे सवाल है? जाहिर है, मैं एक इनपुट स्ट्रीम फ़िल्टर के रूप में डिक्रिप्शन को कार्यान्वित कर सकता हूं, लेकिन मुझे यकीन नहीं है कि एक्सएमएल को जिस तरीके से मैं वर्णन कर रहा हूं उसे पार्स करना संभव है; दूसरे चरण की जानकारी इकट्ठा करने के लिए जितना अधिक दस्तावेज़ चलाना आवश्यक है, और उसके बाद दस्तावेज़ को रिवाइंड करके और इसे फिर से गुजरने के लिए इसे गुजरने के लिए, दस्तावेज़ के सभी हिस्सों को आदर्श रूप से जारी करना जो अब उपयोग में नहीं हैं वे पारित कर दिया गया है।

उत्तर

3

आप BufferedInputStream का उपयोग बहुत बड़े बफर आकार के साथ कर सकते हैं और विस्तार कक्षा कार्य और reset() के बाद का उपयोग कर सकते हैं।

यदि विस्तार वर्ग की आवश्यकता वाले हिस्सों को फ़ाइल में बहुत दूर है, तो यह अत्यधिक स्मृति गहन हो सकता है, हालांकि।

एक और सामान्य समाधान आपके BufferedInputStream लिखने के लिए होगा - अगर काम को बफर करने वाले डेटा को कुछ प्रीसेट थ्रेसहोल्ड से अधिक किया जाता है तो डिस्क पर बफर होता है।

1

आप XOM द्वारा रुचि हो सकती है:

XOM यह एक दोहरी स्ट्रीमिंग/वृक्ष-आधारित एपीआई है कि में काफी अनोखा है। पेड़ में व्यक्तिगत नोड्स संसाधित हो सकते हैं जबकि दस्तावेज़ अभी भी बनाया जा रहा है। अंतर्निहित पार्सर के रूप में लगभग तेज़ी से संचालित करने के लिए XOM प्रोग्राम को सक्षम बनाता है। पर दस्तावेज़ के लिए प्रतीक्षा करने की आवश्यकता नहीं है, इससे पहले कि आप इसके साथ काम करना शुरू कर सकें, पूरी तरह से पार्स हो जाएं।

एक्सओएम बहुत मेमोरी कुशल है। यदि आप मेमोरी में एक संपूर्ण दस्तावेज़ पढ़ते हैं, तो XOM जितना संभव हो उतना कम स्मृति उपयोग करता है। अधिक महत्वपूर्ण बात यह है कि एक्सओएम आपको फ़िल्टर दस्तावेज़ों की अनुमति देता है क्योंकि वे बनाए गए हैं, आपको उस पेड़ में के हिस्सों को बनाने की आवश्यकता नहीं है, जिसमें आप रुचि नहीं रखते हैं। उदाहरण के लिए, आप बिल्डिंग टेक्स्ट नोड्स को छोड़ सकते हैं जो केवल सफेद स्थान का प्रतिनिधित्व करते हैं, यदि ऐसी सफेद जगह आपके एप्लिकेशन में महत्वपूर्ण नहीं है। आप दस्तावेज़ के टुकड़े को टुकड़े से भी संसाधित कर सकते हैं और जब आप इसके साथ काम करते हैं तो प्रत्येक टुकड़ा निकाल दें। एक्सओएम आकार में गीगाबाइट्स को संसाधित करने के लिए प्रयुक्त होता है।

+1

यह एक दिलचस्प, और संभावित रूप से उपयोगी दृष्टिकोण की तरह दिखता है, लेकिन में कहीं भी प्रलेखन में यह वर्णन नहीं करता है कि दस्तावेज़ को आपके द्वारा वर्णित तरीके से पार्सिंग को नियंत्रित करने का एक तरीका है। मुझे विश्वास है कि यह _can_ है लेकिन क्षमता ऐसी तरीके से प्रलेखित नहीं है जो खोजना उचित है। –

7

यह StAX (JSR 173) के लिए नौकरी की तरह लगता है। स्टैक्स एक पुल पार्सर है, जिसका अर्थ यह है कि यह एसएक्स जैसे ईवेंट आधारित पार्सर की तरह कम या ज्यादा काम करता है, लेकिन आपके पास पढ़ने के लिए, कौन से तत्वों को खींचना है, पर अधिक नियंत्रण है, ...

इसकी उपयोगिता समाधान आपके विस्तार वर्गों पर वास्तव में क्या कर रहा है, इस पर निर्भर करेगा, यदि आपके कार्यान्वयन पर नियंत्रण है, आदि ...

मुख्य बिंदु यह है कि यदि दस्तावेज़ बहुत बड़ा है, तो आप शायद एक ईवेंट आधारित पार्सर और पेड़ आधारित नहीं है, इसलिए आप बहुत सारी मेमोरी का उपयोग नहीं करेंगे।

एसएक्स के कार्यान्वयन SUN (SJSXP), Codehaus या कुछ अन्य प्रदाताओं से मिल सकते हैं।

+0

यह आशाजनक लग रहा है, जब तक मैं इसे कुशलता से इसमें लगा सकता हूं। ऐसा लगता है कि मुझे अपने एपीआई के ग्राहकों को स्टैक्स का पर्दाफाश करना होगा, जो कि आदर्श से कम है, लेकिन कम से कम ऐसा लगता है कि क्षमताओं की संभावना है। क्या आप अपनी पोस्ट को सूची के बजाय अनुशंसित कार्यान्वयन के साथ संशोधित कर सकते हैं? –

+1

मुझे पता है कि यह एक पुराना उत्तर/टिप्पणी है, लेकिन कुछ libs हैं जो स्टैक्स के शीर्ष पर थोड़ा अधिक सुविधा जोड़ सकते हैं (और कुछ निम्न स्तर के विवरण अलग कर सकते हैं), उदाहरण के लिए StaxMate [http://staxmate.codehaus.org/Tutorial ]। यह अभी भी वृद्धिशील पार्सिंग/लेखन के लिए अनुमति देता है, लेकिन लिखने के लिए कोड की मात्रा को कम करता है। – StaxMan

3

को देख सिफारिश करेंगे मैं उस फ़ाइल में बाइट्स decrypts InputStream के एक कस्टम कार्यान्वयन लिखते थे और उसके बाद SAX का उपयोग जिसके परिणामस्वरूप XML को पार्स करने के रूप में यह धारा बाहर आ जाता है।

SAXParserFactory.newInstance().newSAXParser().parse(
    new DecryptingInputStream(), 
    new MyHandler() 
); 
0

XOM लाइब्रेरी को देखें। उदाहरण जो आप खोज रहे हैं वह स्रोत वितरण की नमूने निर्देशिका में StreamingExampleExtractor.java है। यह एक बड़े एक्सएमएल दस्तावेज के स्ट्रीमिंग पार्स को केवल विशिष्ट नोड्स बनाने, उन्हें संसाधित करने और उन्हें हटाने के लिए एक तकनीक दिखाता है। यह एक सैक्स दृष्टिकोण के समान है, लेकिन इसमें बहुत अधिक पार्सिंग क्षमता है ताकि स्ट्रीमिंग पार्स को आसानी से हासिल किया जा सके।

यदि आप NUX पर उच्च स्तर पर काम करना चाहते हैं। यह एक उच्च स्तरीय स्ट्रीमिंग xpath API प्रदान करता है जो xpath का मूल्यांकन करने के लिए आवश्यक स्मृति में डेटा की मात्रा को केवल पढ़ता है।