2009-05-11 5 views
7

मेरे पास निम्नलिखित संरचना में एक बड़ी एक्सएमएल फ़ाइल (लगभग 10 एमबी) है:एक एक्सएमएल के अंत में नया नोड जोड़ने का सबसे तेज़ तरीका?

<Errors> 
    <Error>.......</Error> 
    <Error>.......</Error> 
    <Error>.......</Error> 
    <Error>.......</Error> 
    <Error>.......</Error> 
</Errors> 

</errors > टैग से पहले अंत में एक नया नोड < त्रुटि > जोड़ने की आवश्यकता है। .NET में इसे प्राप्त करने का सबसे तेज़ तरीका क्या है?

+0

आप इसे कैसे लिख रहे हैं? डीओएम का उपयोग करना? SAX? प्रत्यक्ष लिखता है? :- पी मैं व्यक्तिगत रूप से डोम दृष्टिकोण पसंद करता हूं; आप केवल त्रुटियों नोड तक पहुंचें और appendChild() को कॉल करें। –

+2

कृपया इस स्थिति के लिए "सबसे तेज़" परिभाषित करें; क्या आपका मतलब है "निष्पादित करने के लिए सबसे तेज़" या "विकसित करने के लिए सबसे तेज़"? –

+0

"निष्पादित करने के लिए सबसे तेज़" –

उत्तर

10

आपको XML समावेशन तकनीक का उपयोग करने की आवश्यकता है।

आपका error.xml (बदल नहीं है, सिर्फ एक ठूंठ को पढ़ने के लिए एक्सएमएल पारसर्स द्वारा प्रयुक्त।):

<?xml version="1.0"?> 
<!DOCTYPE logfile [ 
<!ENTITY logrows  
SYSTEM "errorrows.txt"> 
]> 
<Errors> 
&logrows; 
</Errors> 

आपका errorrows.txt फ़ाइल (परिवर्तन, XML पार्सर यह समझ नहीं करता है) :

<Error>....</Error> 
<Error>....</Error> 
<Error>....</Error> 

फिर, एक प्रविष्टि जोड़ने के लिए errorrows.txt रहे हैं:

using (StreamWriter sw = File.AppendText("logerrors.txt")) 
{ 
    XmlTextWriter xtw = new XmlTextWriter(sw); 

    xtw.WriteStartElement("Error"); 
    // ... write error messge here 
    xtw.Close(); 
} 

या आप भी .NET 3.5 XElement उपयोग कर सकते हैं, और संलग्न StreamWriter के लिए पाठ:

using (StreamWriter sw = File.AppendText("logerrors.txt")) 
{ 
    XElement element = new XElement("Error"); 
    // ... write error messge here 
    sw.WriteLine(element.ToString()); 
} 

भी Microsoft's article Efficient Techniques for Modifying Large XML Files

0

तेज विधि तो आप की जरूरत है, एक XmlReader का उपयोग कर फ़ाइल में पढ़ने जा करने के लिए, और बस प्रत्येक XmlWriter का उपयोग कर जब आप बिंदु है जिस पर आप बंद करने </Errors> टैग सामना करने के लिए मिलता है एक नई धारा को नोड पढ़ नकल होने की संभावना है 'पढ़ने और डुप्लिकेट' चक्र को समाप्त करने से पहले अपने अतिरिक्त <Error> तत्व को आउटपुट करने के लिए। इस तरह पूरे दस्तावेज़ को डीओएम (XmlDocument कक्षा) में पढ़ने की तुलना में कठिन होना मुश्किल है, लेकिन बड़ी एक्सएमएल फाइलों के लिए, अधिक तेज। माना जाता है कि StreamReader/StreamWriter का उपयोग कुछ हद तक तेज होगा, लेकिन कोड में काम करने के लिए बहुत भयानक होगा।

0

आपकी XML-फ़ाइल कोड में कैसे प्रदर्शित होती है? क्या आप सिस्टम.एक्सएमएल-क्लासेस का उपयोग करते हैं? इस मामले में आप XMLDocument.AppendChild का उपयोग कर सकते हैं।

7

सबसे पहले, मैं System.Xml.XmlDocument को अयोग्य कर दूंगा क्योंकि it is a DOM जिसके लिए इसे जोड़ने से पहले स्मृति में पूरे पेड़ को पार्सिंग और निर्माण करने की आवश्यकता होती है। इसका मतलब है कि आपका 10 एमबी टेक्स्ट मेमोरी में 10 एमबी से अधिक होगा। इसका मतलब है कि यह "स्मृति गहन" और "समय लेने वाला" है।

दूसरा, मैं System.Xml.XmlReader को अयोग्य कर दूंगा क्योंकि यह requires parsing the entire file इससे पहले कि आप इसे जोड़ सकें, इससे पहले कि आप इसे प्राप्त कर सकें। आपको XmlReader को XmlWriter में कॉपी करना होगा क्योंकि आप इसे संशोधित नहीं कर सकते हैं। इससे पहले कि आप इसे जोड़ सकें, इससे पहले आपके एक्सएमएल को मेमोरी में डुप्लिकेट करना होगा।

XmlDocument और XmlReader स्ट्रिंग परिवर्तन किया जाएगा करने के लिए तेजी से समाधान (जो अपनी ही स्मृति मुद्दे हैं):

string xml = @"<Errors><error />...<error /></Errors>"; 
int idx = xml.LastIndexOf("</Errors>"); 

xml = xml.Substring(0, idx) + "<error>new error</error></Errors>"; 

, समाप्ति टैग बंद काट नई त्रुटि में जोड़ने के लिए, और अंत टैग वापस जोड़ें।

मुझे लगता है कि आप इसके साथ पागल हो सकते हैं और 9 अक्षरों से अपनी फ़ाइल को छोटा कर सकते हैं और इसमें शामिल हो सकते हैं। फ़ाइल में पढ़ना नहीं होगा और ओएस को पृष्ठ लोडिंग को अनुकूलित करने देगा (केवल अंतिम ब्लॉक या कुछ में लोड करना होगा)।

System.IO.FileStream fs = System.IO.File.Open("log.xml", System.IO.FileMode.Open, System.IO.FileAccess.ReadWrite); 
fs.Seek(-("</Errors>".Length), System.IO.SeekOrigin.End); 
fs.Write("<error>new error</error></Errors>"); 
fs.Close(); 

यही एक समस्या मारा है, जब आपके फ़ाइल रिक्त है या होता है केवल "< त्रुटियाँ > </त्रुटियाँ >", जो दोनों के आसानी से लंबाई की जाँच के द्वारा नियंत्रित किया जा सकता है।

+0

ओपनटेक्स्ट() एक स्ट्रीमरडर पढ़ने और लौटने के लिए एक फ़ाइल खोलता है। –

+0

वास्तव में, धन्यवाद। फिक्स्ड? –

+0

ग्रीट! आपने एक बहुत बड़ी समस्या हल की है, मुझे नहीं पता कि यह जवाब 1k –

3

सबसे तेज़ तरीका शायद प्रत्यक्ष फ़ाइल पहुंच होगी।

using (StreamWriter file = File.AppendText("my.log")) 
{ 
    file.BaseStream.Seek(-"</Errors>".Length, SeekOrigin.End); 
    file.Write(" <Error>New error message.</Error></Errors>"); 
} 

लेकिन आप सभी अच्छी एक्सएमएल सुविधाओं को खो देते हैं और फ़ाइल को आसानी से दूषित कर सकते हैं।

+1

यही वही है जो मैंने सुझाव दिया होगा। –

+0

मैं इसका प्रयास कर रहा हूं लेकिन 'अपेंड मोड में खोले गए फ़ाइल में पहले मौजूद डेटा को ओवरराइट करने में असमर्थ' प्राप्त करें। सिंक लाइन पर त्रुटि। क्या उदाहरण सही है? – Simon

+0

नहीं, परीक्षा सही नहीं है, लेकिन इसे काम करने के लिए आपको बस इतना करना है कि 'नया स्ट्रीमवाइटर (फ़ाइल' के साथ 'File.AppendText (...)' को प्रतिस्थापित करें।ओपन (filePath, FileMode.Open, FileAccess.Write) ' –

1

मैं आपकी फ़ाइल लोड करने के लिए XmlDocument या XDocument का उपयोग करूंगा और फिर तदनुसार इसका उपयोग करूँगा।

मैं फिर इस एक्सएमएल दस्तावेज़ को स्मृति में कैशिंग करने की संभावना को देखता हूं ताकि आप फ़ाइल को जल्दी से एक्सेस कर सकें।

आपको किस गति की आवश्यकता है? क्या आपके पास पहले से ही एक प्रदर्शन बाधा है या आप एक की उम्मीद कर रहे हैं?

+0

एक्सएमएल डॉक्यूमेंट एक डीओएम मॉडल है जो एक्सएमएलआरडर में एसएएक्स की तुलना में धीमा है। XmlDocument को ऑब्जेक्ट के रूप में स्मृति में पूरे 10 एमबी का प्रतिनिधित्व करने की आवश्यकता होगी (इसलिए 10 एमबी से अधिक कुल)। XmlReader तेज़ होगा (मैं निश्चित रूप से XmlDocument पर XmlDocument बनाया गया है) लेकिन आपको अभी भी पूरे दस्तावेज़ को पार्स करना होगा। न तो, मेरे लिए, अगर सभी रमेश कर रहे हैं तो "तेज़" के रूप में अर्हता प्राप्त करें एक लॉग फ़ाइल में संलग्न है (जो मामला प्रतीत होता है)। –

+0

मैं पूरी तरह से सहमत हूं, लेकिन मैं हमेशा टेक्स्ट एपेंड के साथ एक्सएमएल लिखने से बचना चाहता हूं। मेरा जवाब यह पता लगाना था कि क्या वह दस्तावेज़ को स्मृति में लोड कर सकता है और फिर उसे लिख सकता है। वह तेज़ होगा। फिर एक और प्रक्रिया जो कभी-कभी फ़ाइल में XmlDocument लिखती है। यह सब परिदृश्य पर निर्भर करता है। –

1

इस आजमाएं:

 var doc = new XmlDocument(); 
     doc.LoadXml("<Errors><error>This is my first error</error></Errors>"); 

     XmlNode root = doc.DocumentElement; 

     //Create a new node. 
     XmlElement elem = doc.CreateElement("error"); 
     elem.InnerText = "This is my error"; 

     //Add the node to the document. 
     if (root != null) root.AppendChild(elem); 

     doc.Save(Console.Out); 
     Console.ReadLine(); 
+1

यह निश्चित रूप से सबसे तेज़ तरीका नहीं है। –

0

यहाँ कैसे सी में यह करने के लिए है, .नेट समान होना चाहिए।

खेल फ़ाइल के अंत तक सरल कूदना, टैग पर वापस छोड़ना, नई त्रुटि रेखा जोड़ना और एक नया टैग लिखना है।

#include <stdio.h> 
#include <string.h> 
#include <errno.h> 

int main(int argc, char** argv) { 
     FILE *f; 

     // Open the file 
     f = fopen("log.xml", "r+"); 

     // Small buffer to determine length of \n (1 on Unix, 2 on PC) 
     // You could always simply hard code this if you don't plan on 
     // porting to Unix. 
     char nlbuf[10]; 
     sprintf(nlbuf, "\n"); 

     // How long is our end tag? 
     long offset = strlen("</Errors>"); 

     // Add in an \n char. 
     offset += strlen(nlbuf); 

     // Seek to the END OF FILE, and then GO BACK the end tag and newline 
     // so we use a NEGATIVE offset. 
     fseek(f, offset * -1, SEEK_END); 

     // Print out your new error line 
     fprintf(f, "<Error>New error line</Error>\n"); 

     // Print out new ending tag. 
     fprintf(f, "</Errors>\n"); 

     // Close and you're done 
     fclose(f); 
} 
0

देखें (फ़ाइल के अंत की मांग और फिर पीछे की ओर बंद टैग की लंबाई चलती की तरह) स्ट्रिंग आधारित तकनीकों का प्रयोग अप्रत्याशित की चपेट में है, लेकिन दस्तावेज़ संरचना में पूरी तरह कानूनी बदलाव।

आपके द्वारा सामना की जाने वाली सबसे बड़ी समस्या चुनने के लिए दस्तावेज़ किसी भी प्रकार की सफेद जगह के साथ समाप्त हो सकता है। यह किसी भी टिप्पणी या प्रसंस्करण निर्देशों के साथ समाप्त हो सकता है। और क्या होता है यदि शीर्ष-स्तरीय तत्व का नाम Error नहीं है?

और यहाँ एक स्थिति है कि स्ट्रिंग परिवर्तन का उपयोग कर पूरी तरह से विफल हो जाता है पता लगाने के लिए है:

<Error xmlns="not_your_namespace"> 
    ... 
</Error> 

आप एक XmlReader का उपयोग करते हैं एक्सएमएल कार्रवाई करने के लिए, जबकि यह जितनी जल्दी EOF करने की मांग के रूप में नहीं किया जा सकता है, यह भी अनुमति देगा आप इन सभी संभावित अपवाद स्थितियों को संभालने के लिए।

+0

वह फ़ाइल जो उसने प्रस्तुत की है वह एक लॉग फ़ाइल की तरह दिखती है और मुझे लगता है कि वह उस बिंदु पर टक्कर मार रहा है जहां यह तेजी से धीमा हो रहा है, इसलिए उसका सवाल है। कहने का पर्याप्त कारण है कि मुझे लगता है कि लॉग प्रारूप पूरी तरह से उसके नियंत्रण में है। –

+0

यह उन धारणाओं को बनाने के लिए अक्सर पूरी तरह से ठीक हो सकता है। मुझे बहुत सारे कोड को ठीक करना पड़ा जहां डेवलपर ने गलत अनुमान लगाया था। उन मामलों में से अधिकांश में, डेवलपर को यह भी पता नहीं था कि वह अनुमान लगा रहा था। –

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

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