从 XmlReader 读取流,base64 解码并将结果写入文件

Read stream from XmlReader, base64 decode it and write result to file

基本上,我想从 XmlReader 中提取流并直接将其 base64 解码为文件。

可以看到XML文件的结构。要获得我必须使用 ReadInnerXml() 的值。是否可以使用 ReadValueChunk 代替?

这是我当前的代码:

using (XmlReader reader = XmlReader.Create("/your/path/47311.xml"))
{
    while(reader.Read())
    {
        if (reader.IsStartElement () && reader.NodeType == XmlNodeType.Element) {
            switch (reader.Name) {
            case "ttOutputRow":
                reader.ReadToDescendant ("cKey");
                switch (reader.ReadInnerXml ()) {
                case "findMe":
                    reader.ReadToNextSibling ("cValue");
                    // here begins the interesting part
                    char[] buffer = new char[4096];
                    int charRead;
                    using (var destStream = File.OpenWrite ("/your/path/47311.jpg")) {
                        while ((charRead = reader.ReadValueChunk (buffer, 0, 4096)) != 0) {
                            byte[] decodedStream = System.Convert.FromBase64String (new string (buffer));
                            await destStream.WriteAsync(decodedStream, 0, decodedStream.Length);
                            Console.WriteLine ("in");
                        }

                    }
                    break;
                default:
                    break;
                }
                break;
            default:
                break;
            }
        }
    }
}

目前,他没有读入值。

我不能为此使用 ReadValueChunk 吗?如何在不牺牲太多内存的情况下直接使用来自 XmlReader 的流?

编辑:

根据dbc我修改了我的代码。这是我目前使用的:

using (XmlReader reader = XmlReader.Create("test.xml"))
{
    while(reader.Read())
    {
        if (reader.IsStartElement () && reader.NodeType == XmlNodeType.Element) {
            switch (reader.Name) {
            case "ttOutputRow":
                reader.ReadToDescendant ("cKey");
                switch (reader.ReadInnerXml ()) {
                case "findMe":
                    reader.ReadToNextSibling ("cValue");
                    byte[] buffer = new byte[40960];
                    int readBytes = 0;
                    using (FileStream outputFile = File.OpenWrite ("test.jpg")) 
                    using (BinaryWriter bw = new BinaryWriter(outputFile))
                    {
                        while ((readBytes = reader.ReadElementContentAsBase64(buffer, 0, 40960)) > 0) {
                            bw.Write (buffer, 0, readBytes);
                            Console.WriteLine ("in");
                        }

                    }
                    break;
                default:
                    break;
                }
                break;
            default:
                break;
            }
        }
    }
}

Here你可以找到一个测试文件。实际文件稍微大一点,因此需要更多时间。

以上代码没有按预期工作。速度很慢,提取的图像大部分是黑色的(已损坏)。

为了对您的问题给出明确的答案,我需要查看您正在尝试阅读的 XML。不过,有两点:

  1. 根据documentation for Convert.FromBase64String:

    The FromBase64String method is designed to process a single string that contains all the data to be decoded. To decode base-64 character data from a stream, use the System.Security.Cryptography.FromBase64Transform class.

    因此,您的问题可能出在以块的形式解码内容而不是以块的形式读取内容。

  2. 您可以使用 XmlReader.ReadElementContentAsBase64 or XmlReader.ReadElementContentAsBase64Async 来达到这个目的。来自文档:

    This method reads the element content, decodes it using Base64 encoding, and returns the decoded binary bytes (for example, an inline Base64-encoded GIF image) into the buffer.

    事实上,文档中的示例演示了如何从 XML 文件中提取 base64 编码的图像并将其写入块中的二进制文件。