我想在解析之前检测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
如果我ReadToEnd
或MoveToContent
,则表示已成功结束。 EndOfStream
true 然后。
如果我通过Seek
或Position
将位置重置为0(例如),则new StreamReader
始终显示EndOfStream
为真。
问题是uploadStream
是一个我无法关闭的流。
这是http上传流的 SharpZipLib 流。所以我无法关闭这个流。我只能使用它。
唯一不好的是因为Position
和Seek
不起作用......只是因为ReadToEnd
在此Position
上传递。 - 否则它会起作用。我想!
也许你可以帮助我解决这个问题: - )
非常感谢您提前!
答案 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);