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

C# 从MemoryStream获取子字符串,而不将整个流转换为字符串,c#,substring,string-matching,memorystream,C#,Substring,String Matching,Memorystream,我希望能够高效地从MemoryStream(最初来自zip中的xml文件)获取子字符串。目前,我将整个MemoryStream读取为一个字符串,然后搜索所需xml节点的开始和结束标记。这很好,但文本文件可能非常大,因此我希望避免将整个MemoryStream转换为字符串,而是直接从流中提取所需的xml文本部分 最好的办法是什么 string xmlText; using (var zip = ZipFile.Read(zipFileName)) { var ze = zip[zipPat

我希望能够高效地从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);
字符串xmlText;
使用(var zip=ZipFile.Read(zipFileName))
{
var ze=zip[zipPath];
使用(var ms=new MemoryStream())
{
提取物(ms);
ms.Position=0;
使用(var sr=新的StreamReader(ms))
{
xmlText=sr.ReadToEnd();
}
}
}
字符串startTag=“”;
字符串endTag=“”;
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 (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();
            }
        }
使用(var ms=new MemoryStream())
{
提取物(ms);
ms.Position=0;
使用(var sr=新的StreamReader(ms))
{
bool adding=false;
字符串startTag=“”;
字符串endTag=“”;
StringBuilder text=新的StringBuilder();
而(sr.Peek()>=0)
{
字符串tmp=sr.ReadLine();
如果(!添加和&tmp.Contains(startTag))
{
加法=真;
}
如果(添加)
{
追加文本(tmp);
}
if(tmp.Contains(endTag))
打破
}
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
            }
        }
    }
}
字符串xmlText;
使用(var zip=ZipFile.Read(zipFileName))
{
var ze=zip[zipPath];
使用(var ms=new MemoryStream())
{
提取物(ms);
ms.Position=0;
使用(var xml=XmlReader.Create(ms))
{
if(xml.ReadToFollowing(“someTag”))
{
xmlText=xml.ReadInnerXml();
}
其他的
{
//找不到
}
}
}
}

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

您可以从内存流创建一个
XmlReader
,以避免将整个文件加载到内存。@juharr:将其作为答案写下来。另一种方法将是一种巨大的痛苦,可能无法正常工作。那是什么zip库?您当前的方法将整个文件提取到MemoryStream中,因此它可能导致大文件出现内存不足异常。在.NET4.5中可以使用DotNetZip。我需要使用.NET 4.0。似乎您可以使用而不是
。提取
,然后使用
XmlReader。在该流上创建
,而不是MemoryStream