C#EndOfStream始终为true - Seek / Position to 0不起作用

时间:2016-06-18 11:00:34

标签: c# c#-4.0 stream inputstream sharpziplib

我想在解析之前检测XML文档的编码。所以我发现堆栈溢出这个脚本。

public static XElement GetXMLFromStream(Stream uploadStream)
{
    /** Remember position */
    var position = uploadStream.Position;

    /** Get encoding */
    var xmlReader = new XmlTextReader(uploadStream);
    xmlReader.MoveToContent();

    /** Move to remembered position */
    uploadStream.Seek(position, SeekOrigin.Begin); // with "pos" = 0 it not works, too
    uploadStream.Seek(position, SeekOrigin.Current); // if I remove this I have the same issue!

    /** Read content with detected encoding */
    var streamReader = new StreamReader(uploadStream, xmlReader.Encoding);
    var streamReaderString = streamReader.ReadToEnd();
    return XElement.Parse(streamReaderString);
}

但它不起作用。 我总是得到EndOfStream true 。但它不是!!!! -.-

例如,我有字符串<test></test>。 开始:0,结束:13

如果我ReadToEndMoveToContent,则表示已成功结束。 EndOfStream true 然后。

如果我通过SeekPosition将位置重置为0(例如),则new StreamReader始终显示EndOfStream 为真

问题是uploadStream是一个我无法关闭的流。

这是http上传流的 SharpZipLib 流。所以我无法关闭这个流。我只能使用它。

唯一不好的是因为PositionSeek不起作用......只是因为ReadToEnd在此Position上传递。 - 否则它会起作用。我想!

也许你可以帮助我解决这个问题: - )

非常感谢您提前!

示例: Example of <code>EndOfStream</code> is true - but the Position is not at the end!

2 个答案:

答案 0 :(得分:2)

这种方法从根本上与某些类型的输入流不兼容。 Streams不需要支持Seek。实际上,Stream具有专门用于检测Seek是否可用的属性,称为CanSeek。代码需要考虑Seek可能失败。

简单但非常节省内存的方法是将您的信息流内容复制到MemoryStream。那个人确实支持Seek,然后你可以用它做任何你想做的事情。您使用ReadToEnd()这一事实表明数据不是很大,以至于内存使用会导致问题,所以您可能只是采用这种方式。

注意:如文档所述,如果不支持Seek,则应该抛出NotSupportedException。看起来您正在处理的流实现,它不受支持,但没有正确实现。我希望至少CanSeek为您返回false,这样您仍然可以可靠地检测到这一点。

答案 1 :(得分:1)

选项1:

XElement有一个Load()方法,可直接从xml流中读取。它将在内部管理您的编码。并且通过避免不必要的字符串来提高效率。那么为什么不使用它呢。

XElement.Load(uploadStream);

选项2:

如果您真的想使用字符串,请不要使用 new XmlTextReader()。 XmlTextReader.Create()具有更多功能,所以请改为:

var xmlReader = XmlTextReader.Create(uploadStream);
var streamReaderString = xmlReader.ReadOuterXml();
return XElement.Parse(streamReaderString);