如何预先添加流?

发布于 2024-12-17 12:54:37 字数 401 浏览 0 评论 0原文

我将 blob 作为字节数组从数据库中加载,并将它们放入内存流中,以便可以将它们加载到 xml 文档中进行解析。

然而,有些 blob 具有多个根节点,这会导致解析器崩溃。

我的解决方案是创建一个包含整个 blob 的新根节点。

我可以使用流编写器很好地添加到末尾,但是我不知道如何添加到开头。

如何添加到流之前?


更新
我在让它发挥作用时遇到了太多麻烦。我提取的“XML”不是正确的 XML,我必须不断添加越来越多的正则表达式才能在 XmlDocument 加载之前删除错误的 XML。我最终使用 HtmlAgilityPack 解析出 XML 的有效部分,并将它们放入自己的 xml 文档中。这不是最好的解决方案,但它有效。 叹息

I'm loading blobs out of a database as a byte array and I put them in a memory stream so that I can load them into an xmldocument for parsing.

However there are blobs that have multiple root nodes, this causes the parser to blow up.

My solution is to just make a new root node that encompasses the whole blob.

I can add onto the end just fine with a streamwriter however I can't figure out how to add onto the beginning.

How can I prepend to a stream?


Update
I was having too much trouble getting this to work. The "XML" I was extracting was not proper XML and I kept on having to add more and more regexes to remove bad XML before the XmlDocument Load. I ended up using the HtmlAgilityPack to parse out my valid sections of XML and I put those inside their own xml documents. Not the nicest solution but it works. Sigh

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

删除→记忆 2024-12-24 12:54:37

由于您已经从数据库中获得了 byte[] 数组,因此将数组前后的更多字节写入内存流应该很容易:

// bytes from db
byte[] multipleNodes = Encoding.UTF8.GetBytes("<first>..</first><second>..</second><third>..</third>");

using (var ms = new MemoryStream())
{
    // write opening tag
    byte[] newRoot = Encoding.UTF8.GetBytes("<newRoot>");
    ms.Write(newRoot, 0, newRoot.Length);

    ms.Write(multipleNodes, 0, multipleNodes.Length);

    // write opening tag
    byte[] closeNewRoot = Encoding.UTF8.GetBytes("</newRoot>");
    ms.Write(closeNewRoot, 0, closeNewRoot.Length);

    // reset cursor position before pass it to xmldoc
    ms.Position = 0;

    var xml = new XmlDocument();
    xml.Load(ms);

    Console.WriteLine(xml.InnerXml);
}

但是由于 XmlDocument 还提供了 LoadXml( str),我觉得操作字符串应该是更直接的解决方案:

// bytes from db
byte[] multipleNodes = Encoding.UTF8.GetBytes("<first>..</first><second>..</second><third>..</third>");

string stringFromBlob = Encoding.UTF8.GetString(multipleNodes);
string withRootNode = string.Format("<newRoot>{0}</newRoot>", stringFromBlob);

var xml = new XmlDocument();
xml.LoadXml(withRootNode);

Console.WriteLine(xml.InnerXml);

Since you already have byte[] array from DB, writing more bytes before and after the array to memory stream should be easy:

// bytes from db
byte[] multipleNodes = Encoding.UTF8.GetBytes("<first>..</first><second>..</second><third>..</third>");

using (var ms = new MemoryStream())
{
    // write opening tag
    byte[] newRoot = Encoding.UTF8.GetBytes("<newRoot>");
    ms.Write(newRoot, 0, newRoot.Length);

    ms.Write(multipleNodes, 0, multipleNodes.Length);

    // write opening tag
    byte[] closeNewRoot = Encoding.UTF8.GetBytes("</newRoot>");
    ms.Write(closeNewRoot, 0, closeNewRoot.Length);

    // reset cursor position before pass it to xmldoc
    ms.Position = 0;

    var xml = new XmlDocument();
    xml.Load(ms);

    Console.WriteLine(xml.InnerXml);
}

But since XmlDocument also provide LoadXml(str), I feel manipulating the string should be more straight forward solution:

// bytes from db
byte[] multipleNodes = Encoding.UTF8.GetBytes("<first>..</first><second>..</second><third>..</third>");

string stringFromBlob = Encoding.UTF8.GetString(multipleNodes);
string withRootNode = string.Format("<newRoot>{0}</newRoot>", stringFromBlob);

var xml = new XmlDocument();
xml.LoadXml(withRootNode);

Console.WriteLine(xml.InnerXml);
说好的呢 2024-12-24 12:54:37

你不能直接。这导致两个选择:

  • 在加载 blob 之前将开始标记写入内存流
  • 创建第二个内存流,写入开始标记,将第一个标记复制到第二个...

You can't directly. This leads to two options:

  • write in an opening tag into the memorystream prior to loading the blobs
  • create a second memorystream, write in an opening tag, copy the first into the second...
辞旧 2024-12-24 12:54:37

这是我使用的:

public class CompositeStream : FileStream
{
    Stream[] childStreams;
    int currentStreamIndex = 0;
    Stream currentStream;
    public long totalStreamRead{get; private set;}

    public CompositeStream(string pre, FileStream s_file, string post)
        : base(s_file.SafeFileHandle, FileAccess.Read)
    {
        totalStreamRead = 0;

        MemoryStream s_pre = new MemoryStream();
        MemoryStream s_post = new MemoryStream();

        byte[] b_pre = Encoding.UTF8.GetBytes(pre);
        s_pre.Write(b_pre, 0, b_pre.Length);
        s_pre.Flush();
        s_pre.Seek(0, SeekOrigin.Begin);

        byte[] b_post = Encoding.UTF8.GetBytes(post);
        s_post.Write(b_post, 0, b_post.Length);
        s_post.Flush();
        s_post.Seek(0, SeekOrigin.Begin);

        childStreams = new Stream[] { s_pre, s_file, s_post };

        currentStream = childStreams[currentStreamIndex++];
    }

    public override int Read(byte[] buffer, int offset, int count)
    {
        int totalBytesRead = 0;
        while (count > 0)
        {
            // Read what we can from the current stream
            int numBytesRead = currentStream.Read(buffer, offset, count);
            totalBytesRead += numBytesRead;
            count -= numBytesRead;
            offset += numBytesRead;

            // If we haven't satisfied the read request, 
            // we have exhausted the current stream.
            // Move on to the next stream and loop around to read more data.
            if (count > 0)
            {
                // If we run out of child streams to read from...
                if (currentStreamIndex >= childStreams.Length)
                    break; //get out

                currentStream.Close();
                currentStream = childStreams[currentStreamIndex++];
            }
        }
        totalStreamRead += totalBytesRead;
        return totalBytesRead;
    }
}

This is the one I use:

public class CompositeStream : FileStream
{
    Stream[] childStreams;
    int currentStreamIndex = 0;
    Stream currentStream;
    public long totalStreamRead{get; private set;}

    public CompositeStream(string pre, FileStream s_file, string post)
        : base(s_file.SafeFileHandle, FileAccess.Read)
    {
        totalStreamRead = 0;

        MemoryStream s_pre = new MemoryStream();
        MemoryStream s_post = new MemoryStream();

        byte[] b_pre = Encoding.UTF8.GetBytes(pre);
        s_pre.Write(b_pre, 0, b_pre.Length);
        s_pre.Flush();
        s_pre.Seek(0, SeekOrigin.Begin);

        byte[] b_post = Encoding.UTF8.GetBytes(post);
        s_post.Write(b_post, 0, b_post.Length);
        s_post.Flush();
        s_post.Seek(0, SeekOrigin.Begin);

        childStreams = new Stream[] { s_pre, s_file, s_post };

        currentStream = childStreams[currentStreamIndex++];
    }

    public override int Read(byte[] buffer, int offset, int count)
    {
        int totalBytesRead = 0;
        while (count > 0)
        {
            // Read what we can from the current stream
            int numBytesRead = currentStream.Read(buffer, offset, count);
            totalBytesRead += numBytesRead;
            count -= numBytesRead;
            offset += numBytesRead;

            // If we haven't satisfied the read request, 
            // we have exhausted the current stream.
            // Move on to the next stream and loop around to read more data.
            if (count > 0)
            {
                // If we run out of child streams to read from...
                if (currentStreamIndex >= childStreams.Length)
                    break; //get out

                currentStream.Close();
                currentStream = childStreams[currentStreamIndex++];
            }
        }
        totalStreamRead += totalBytesRead;
        return totalBytesRead;
    }
}
三岁铭 2024-12-24 12:54:37

一种简洁的方法是实现一个 CompositeStreamReader,它将接受多个流,然后按顺序读出它们。

https://web.archive.org/web/20100721082808/http://blogs.msdn.com/b/paolos/archive/2010/04/08/how-to-boost-message-transformations-using -the-xslcompiledtransform-class-extended.aspx 您可以适应,但您可以使用更简单的东西。

A clean way to do this is to implement a CompositeStreamReader that will accept a number of streams and then read them out in order.

There is an implementation of one at https://web.archive.org/web/20100721082808/http://blogs.msdn.com/b/paolos/archive/2010/04/08/how-to-boost-message-transformations-using-the-xslcompiledtransform-class-extended.aspx that you can adapt, but you can get away with something simpler.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文