简体   繁体   English

将许多XML文件合并为一个流

[英]Combine many XML files into single stream

I have many hundreds of XML files that are processed one after another. 我有数百个XML文件,它们是一个接一个地处理的。 I want to apply other, existing code to the data in the files. 我想将其他现有代码应用于文件中的数据。 However, that code is written to expect a single file or a stream representing a single file. 但是,编写该代码是为了期望单个文件或代表单个文件的流。

I had a look at 我看了看

How do I concatenate two System.Io.Stream instances into one? 如何将两个System.Io.Stream实例合并为一个?

However, the StreamEnumerator presented in Marc's answer requires streams to be opened to all the files in question at once. 但是,Marc的答案中提供的StreamEnumerator要求同时向所有有问题的文件打开流。 That doesn't seem like a good approach, given the large number of files in my case. 考虑到我的案例中有大量文件,这似乎不是一个好方法。

The existing code consumes the stream like this: 现有代码会像这样消耗流:

XmlReader reader = XmlReader.Create(xmlStream);

Is there a better way to combine the many files into a single stream? 有没有更好的方法将多个文件合并为一个流?

Well, I would write own class that extends System.IO.Stream and by overloading CanRead and Read methods join those streams on demand. 好吧,我会编写自己的类来扩展System.IO.Stream,并通过重载CanRead和Read方法来按需加入这些流。 Something like this (just a stub of concept, you need to fine tune this code): 这样的事情(只是概念的一部分,您需要微调此代码):

using System;
using System.Diagnostics;
using System.IO;
using System.Xml;

namespace ConsoleApplication1
{

    public class CombinedXmlStream : Stream
    {
        private Stream currentStream, startStream, endStream;
        private String[] files;
        private int currentFile = -2;
        private bool endReached = false;

        private static Stream ToStream(String str)
        {
            MemoryStream stream = new MemoryStream();
            StreamWriter writer = new StreamWriter(stream);
            writer.Write(str);
            writer.Flush();
            stream.Position = 0;
            return stream;
        }

        public CombinedXmlStream(String start, String end, params String[] files)
        {
            this.files = files;
            startStream = ToStream(start);
            endStream = ToStream(end);

        }

        public override bool CanRead { get { return true; } }

        public override bool CanSeek { get { return false; } }

        public override bool CanWrite { get { return false; } }

        public override long Length { get { throw new NotImplementedException(); } }

        public override long Position { get { return 0; } set { } }

        public override void Flush() { throw new NotImplementedException(); }

        public override long Seek(long offset, SeekOrigin origin) { throw new NotImplementedException(); }

        public override void SetLength(long value) { throw new NotImplementedException(); }

        public override void Write(byte[] buffer, int offset, int count) { throw new NotImplementedException(); }

        public override int Read(byte[] buffer, int offset, int count)
        {
            doSwitching();

            int output = currentStream.Read(buffer, offset, count);

            if (output == 0)
            {
                doSwitching(true);
                if (currentStream != null)
                {
                    return Read(buffer, offset, count);
                }
            }

            return output;
        }

        private void doSwitching(bool force = false)
        {
            if (force || currentStream == null || !currentStream.CanRead)
            {
                if (currentStream != null)
                {
                    currentStream.Close();
                    currentStream = null;
                }

                currentFile++;
                if (currentFile == -1)
                {
                    currentStream = startStream;
                }
                else if (currentFile >= files.Length && !endReached)
                {
                    currentStream = endStream;
                    endReached = true;
                }
                else if (!endReached)
                {
                    currentStream = new FileStream(files[currentFile], FileMode.Open);
                }
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Debug.WriteLine("Test me");
            using (XmlReader reader = XmlReader.Create(new CombinedXmlStream("<combined>", "</combined>", @"D:\test.xml", @"D:\test2.xml")))
            {
                //reader.MoveToContent();
                while (reader.Read())
                {
                    if (reader.NodeType == XmlNodeType.Element)
                    {
                        Debug.WriteLine("Node: " + reader.Name);
                    }
                }
            }
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM