从 MemoryStream 获取子字符串而不将整个流转换为字符串

Get substring from MemoryStream without converting entire stream to string

我希望能够从 MemoryStream(最初来自 zip 中的 xml 文件)中高效地获取子字符串。目前,我将整个 MemoryStream 读取为一个字符串,然后搜索我想要的 xml 节点的开始和结束标记。这工作正常,但文本文件可能非常大,所以我想避免将整个 MemoryStream 转换为字符串,而是直接从流中提取所需的 xml 文本部分。

解决此问题的最佳方法是什么?

string xmlText;
using (var zip = ZipFile.Read(zipFileName))
{
    var ze = zip[zipPath];
    using (var ms = new MemoryStream())
    {
        ze.Extract(ms);
        ms.Position = 0;
        using(var sr = new StreamReader(ms))
        {
            xmlText = sr.ReadToEnd();
        }
    }
}

string startTag = "<someTag>";
string endTag = "</someTag>";
int startIndex = xmlText.IndexOf(startTag, StringComparison.Ordinal);
int endIndex = xmlText.IndexOf(endTag, startIndex, StringComparison.Ordinal) + endTag.Length - 1;
xmlText = xmlText.Substring(startIndex, endIndex - startIndex + 1);

假设因为它是 xml 它会有换行符,最好使用 StreamReader ReadLine 并在每一行中搜索您的标签。 (另请注意,将您的 StreamReader 也放入 using 中。)

类似

        using (var ms = new MemoryStream())
        {
            ze.Extract(ms);
            ms.Position = 0;
            using (var sr = new StreamReader(ms))
            {
                bool adding = false;
                string startTag = "<someTag>";
                string endTag = "</someTag>";
                StringBuilder text = new StringBuilder();
                while (sr.Peek() >= 0)
                {
                    string tmp = sr.ReadLine();
                    if (!adding && tmp.Contains(startTag))
                    {
                        adding = true;
                    }
                    if (adding)
                    {
                        text.Append(tmp);
                    }
                    if (tmp.Contains(endTag))
                        break;
                }
                xmlText = text.ToString();
            }
        }

这假定开始和结束标记单独在一行上。如果不是,您可以像最初一样通过获取开始和结束的索引来清理生成的文本字符串。

如果您的文件是有效的 xml 文件,那么您应该能够使用 XmlReader 来避免将整个文件加载到内存中

string xmlText;
using (var zip = ZipFile.Read(zipFileName))
{
    var ze = zip[zipPath];
    using (var ms = new MemoryStream())
    {
        ze.Extract(ms);
        ms.Position = 0;
        using (var xml = XmlReader.Create(ms))
        {
            if(xml.ReadToFollowing("someTag"))
            {
                xmlText = xml.ReadInnerXml();
            }
            else
            {
                // <someTag> not found
            }
        }
    }
}

如果文件无效,您可能希望捕获潜在的异常 xml。