The application is written in UWP. I created an xml file using XmlWriter and wrote the data there. The question is how then, as required, to load the created file into the stream and fill it further, without overwriting the previous records.

StorageFolder logfolder = await ApplicationData.Current.LocalFolder.CreateFolderAsync("Order.xml", CreationCollisionOption.OpenIfExists); StorageFile logfile = await logfolder.CreateFileAsync("Order.xml", CreationCollisionOption.OpenIfExists); using(IRandomAccessStream writestream = await logfile.OpenAsync(FileAccessMode.ReadWrite)) { Stream stream = writestream.AsStreamForWrite(); XmlWriterSettings settings = new XmlWriterSettings(); using(XmlWriter writer = XmlWriter.Create(stream, settings)) { writer.WriteStartElement("Orders"); writer.WriteElementString("Order","First Order"); writer.WriteEndElement(); writer.WriteEndDocument(); writer.Flush(); } 

    3 answers 3

    If you need to constantly add XML data to a stream, you can use fragmentary records and read the XML. To do this, use the XmlWriterSettings.ConformanceLevel and XmlReaderSettings.ConformanceLevel with the value ConformanceLevel.Fragment .

     using System; using System.IO; using System.Xml; namespace ConsoleApplication2 { class Program { static XmlWriterSettings Settings = new XmlWriterSettings { ConformanceLevel = ConformanceLevel.Fragment, CloseOutput = false, }; static void Main(string[] args) { using (MemoryStream stream = new MemoryStream()) { AddElement(stream, "First Order"); PrintStream(stream.ToArray()); Console.WriteLine(); AddElement(stream, "Second Order"); PrintStream(stream.ToArray()); } } static void AddElement(Stream stream, String value) { using (XmlWriter writer = XmlWriter.Create(stream, Settings)) { writer.WriteElementString("Order", value); } } static void PrintStream(Byte[] buffer) { using (MemoryStream stream = new MemoryStream(buffer)) using (StreamReader streamReader = new StreamReader(stream)) { Console.WriteLine(streamReader.ReadToEnd()); } } } } 

    Output to console:

     <Order>First Order</Order> <Order>First Order</Order><Order>Second Order</Order> 
    • and what reason can be in this way of working with xml? MemoryStream still takes the RAM until you finish all the write-read operations. Isn't it easier to keep in mind the collection of objects and episodically serialize it-deserialize? - Bulson
    • @Bulson As you could see work with XML occurs in AddElement and work happens with an object of type Stream , i.e. You can work with all objects that are inherited from the abstract class Stream . An object of the type MemoryStream in the example acts as a mock object for testing. - mals

    I would strongly recommend forgetting all these XmlWriters and streamers and working with xml through Linq to XML.

    • 2
      He is not a panacea for everything. Especially when you read gigabyte files. - Vladislav Khapin

    XML must have a specific structure: the opening tag must have a pairing closing tag. And there should be only one root element. If you simply append to the end of the file, you get several root elements, which will lead to incorrectly formed XML (and the parsers will refuse to work with it).

    To avoid this, there are two approaches.

    1. When using XmlWriter / XmlReader you need to create a new file for writing, open the old file for reading and copy the contents of it to the new one, adding additional records at the end (before closing the root tag). After that, the old file can be deleted, and the new renamed.

    2. Work with XML in memory. Read its contents, for example, in XDocument / XElemnt , add new elements, save to the previous file. Or deserialize into a set of classes using XmlSerializer , add objects, serialize back. The approach from the MaLS response is also applicable.

    There is another option to work with the file as a normal text stream: after opening it, move to the end, find the closing tag, overwrite it with new elements, add a closing tag. But it is inconvenient and fraught with errors.