first, the question
Reviewing the previous article on how to write a very large XML in LINQ without memory overflow, there is always a limitation with LINQ, that is, you must install the. NET Framework 3.5, what if the deployment environment does not have 3.5 installed?
Second, set the target
Set the target to the same as the previous one, but also to the directory of all the files and directories in the output into an XML, here is no longer repeated.
Third, analysis
To analyze, first without the 3.5 framework, do not expect xstremingelement, and then out of the DOM and other In-memory way, these methods can not write a large XML and memory does not overflow.
First look at MSDN on the processing of XML, it is not difficult to see a article about XmlWriter. By the way,XmlWriter is the protagonist of today, but XmlWriter is an abstract class, how to get an example? MS is recommended using the XmlWriter.Create method.
The exact words on MSDN are:
although the Microsoft. NET Framework includes XmlTextWriter Class (The class is XmlWriter class, but the recommended practice in version 2.0 is to use the Create method for creating XmlWriter instance.
Iv. try and realize
1. Let's take a look at XmlWriter how to use it.
A. First, the simplest: This XML contains a root node with the contents of test
using(varwriter =xmlwriter.create (console.out)) {writer. WriteStartDocument (); Writer. WriteElementString ("Root","Test"); Writer. WriteEndDocument (); }//Output Results<?xml version="1.0"encoding="gb2312"?><root>test</root>
B. A little more complicated.
using (var writer = xmlwriter.create (console.out)) { writer. WriteStartDocument (); Writer. WriteStartElement ("root"); Writer. WriteString ("test"); Writer. WriteEndElement (); Writer. WriteEndDocument (); }
The result is exactly the same. However, you can also look at another method,writefullendelement.
using (var writer = xmlwriter.create (console.out)) { writer. WriteStartDocument (); Writer. WriteStartElement ("root"); Writer. WriteString ("test"); Writer. writefullendelement (); Writer. WriteEndDocument ();}
The results of the operation, and the use of writeendelement no difference between the two really no difference?
C. The difference between writefullendelement and writeendelement
In fact, there are some community, do the following experiment, when the content of the middle of the element is removed, that is:
Using WriteEndElement:
using (var writer = xmlwriter.create (console.out)) { writer. WriteStartDocument (); Writer. WriteStartElement ("root"); Writer. WriteEndElement (); Writer. WriteEndDocument ();} // results <?xml version="1.0" encoding="gb2312 "? ><root/>
Using Writefullendelement
using (var writer = xmlwriter.create (console.out)) { writer. WriteStartDocument (); Writer. WriteStartElement ("root"); Writer. Writefullendelement (); Writer. WriteEndDocument ();} // results:<?xml version="1.0" encoding="gb2312 "?><root></root>
The difference: Using writeendelement automatically uses the XML node abbreviation for nodes that do not have content, while writefullendelement enforces the full notation of the XML nodes.
2. Implement
A. Basic implementation
Back to our goal, the need is to write out directories and documents. In order to accomplish this goal, a method is needed:
Private Static voidGetfoldercontent (XmlWriter writer, DirectoryInfo di) {writer. WriteStartElement ("folder"); Writer. WriteAttributeString ("name", Di. Name); foreach(varSubDirinchdi. GetDirectories ()) {getfoldercontent (writer, subdir); } foreach(varFileinchdi. GetFiles ()) {writer. WriteStartElement ("file"); Writer. WriteAttributeString ("name", file. Name); Writer. WriteEndElement (); } writer. Writefullendelement ();}
Entry function:
using (var writer = xmlwriter.create (console.out)) { writer. WriteStartDocument (); var New DirectoryInfo (@ "d:\sourcecode"); Getfoldercontent (writer, di); Writer. WriteEndDocument ();}
To see the output:
<?xml version="1.0"encoding="gb2312"? ><folder name="bin"><folder name="Debug"><file name="ConsoleApplication6.exe"/><file name="ConsoleApplication6.exe.config"/><file name="consoleapplication6.pdb"/><file name="ConsoleApplication6.vshost.exe"/><file name="ConsoleApplication6.vshost.exe.config"/><file name="ConsoleApplication6.vshost.exe.manifest"/></folder><folder name="Release"><file name="ConsoleApplication6.exe"/><file name="ConsoleApplication6.exe.config"/><filename="consoleapplication6.pdb"/><file name="ConsoleApplication6.vshost.exe"/><file name="ConsoleApplication6.vshost.exe.config"/><file name="ConsoleApplication6.vshost.exe.manifest"/></folder></folder>
Oh,no! A lump of XML, it is impossible to see, because XmlWriter default configuration is to produce a minimal XML, rather than a readable XML.
B. Improved, resulting in formatted XML
The change we need to make is to add a setting and look at the code:
using (varnewtrue })) { writer. WriteStartDocument (); var New DirectoryInfo (@ "E:\PDF"); Getfoldercontent (writer, di); Writer. WriteEndDocument ();}
Results:
<?xml version="1.0"encoding="gb2312"? ><folder name="bin"> <folder name="Debug"> <file name="ConsoleApplication6.exe"/> <file name="ConsoleApplication6.exe.config"/> <file name="consoleapplication6.pdb"/> <file name="ConsoleApplication6.vshost.exe"/> <file name="ConsoleApplication6.vshost.exe.config"/> <file name="ConsoleApplication6.vshost.exe.manifest"/> </folder> <folder name="Release"> <file name="ConsoleApplication6.exe"/> <file name="ConsoleApplication6.exe.config"/> <file name="consoleapplication6.pdb"/> <file name="ConsoleApplication6.vshost.exe"/> <file name="ConsoleApplication6.vshost.exe.config"/> <file name="ConsoleApplication6.vshost.exe.manifest"/> </folder></folder>
C. Continuing to improve
See the file/directory row by row, of course, in a short stay, you can see the node write half of the situation, in the use of xstreamingelement also have such a situation, of course, xstreamingelement to solve the problem is more troublesome, but, XmlWriter can be very simple to solve this problem, only need to make a small change to the Getfoldercontent method can be:
Static voidGetfoldercontent (XmlWriter writer, DirectoryInfo di) {writer. WriteStartElement ("folder"); Writer. WriteAttributeString ("name", Di. Name); foreach(varSubDirinchdi. GetDirectories ()) {getfoldercontent (writer, subdir); } foreach(varFiinchdi. GetFiles ()) {writer. WriteStartElement ("file"); Writer. WriteAttributeString ("name", FI. Name); Writer. WriteEndElement (); } writer. Writefullendelement (); writer. Flush ();}
Add a flush call, and then look at the output effect, of course, if too fast, you can also use CTRL + C to interrupt program execution, you can also find that basically every time the output is to a folder to the end of the place.
C # Operations XML (v)