XmlReader 异常处理 - IEnumerable
本文关键字:IEnumerable 异常处理 XmlReader | 更新日期: 2023-09-27 18:31:54
我正在读取一个非常大的XML文件,我必须将其作为流读取,如下所示:
public IEnumerable<something> GetStuff()
{
foreach(var gzipStream in GetGZips())
{
using (var reader = XmlReader.Create(gzipStream, new XmlReaderSettings{ CheckCharacters = false }))
{
reader.MoveToContent();
while (reader.Read()) //<-- Exception here
{
//Do stuff
yield return something;
}
}
}
}
我在处理过程中收到无效的字符异常:
' ', hexadecimal value 0x19, is an invalid character. Line 655, position 45.
鉴于不允许在 try-catch 中产生返回 - 在发生错误的情况下,简单地中止当前 Xml 文档的处理(并完成枚举)的好方法是什么?
try/finally 不好 - 因为异常会破坏整个 IEnumerable 的处理。
我无法对文件执行任何预处理。
如果你真的不能做任何预处理,并且绝对必须在解析XML时生成枚举,那么如果你把你的while循环替换为:
bool IsMoreXml = true;
while (IsMoreXml)
{
var ValuesRead = null; //not sure what you're reading
try
{
IsMoreXml = reader.Read();
if(!IsMoreXml) break;
//Do Stuff
ValuesRead = whateverwereadfromxml;
}
catch (XmlException ex)
{
//do what you gotta do
break;
}
if(ValuesRead != null)
yield return ValuesRead;
}
不过,您应该处理其他可能的异常,但不确定您是否正在处理从何处调用它的异常。它不优雅,但我不确定你的限制是什么(例如,没有预处理)
我只是在处理同样的事情。 我知道这很老,但我想我会把它放在这里供参考。
我打算提出一个要点,但我认为在 GitHub 上查看提交会更有帮助。
https://github.com/DewJunkie/Log2Console/commit/fb000c0a97c6762b619d213022ddc750bd9254ae如果使用 winmerge 比较以前的版本,则会更清楚地了解更改。
虽然您不能在 try catch 中返回产量,但您可以使用另一个函数返回单个解析的实例。 尝试捕获将在第二个函数中。 我使用正则表达式将日志拆分为单个记录。 我假设即使在大文件中,单个记录仍然可以放入几 KB 的缓冲区中。 我也会想象正则表达式有一些开销,但我主要担心的是丢失数据。
我实际上花了几个小时编写一个解析器,当我进行测试时,我意识到我的解析器的肉是这个正则表达式,我实际上甚至不需要其余的。
TLDR;
旧方法,与你所拥有的非常相似
while(!xmlreader.eof){xmlreader.read();}
新方法
IEnumerable<Foo> ParseFile(stream){
foreach(var match in Regex.Matches(xmlText,$"<(/?)''s*(XML_RECORD_ELEMENT)[^<>]*(/?)>")
{/*logic to split xml based on matches.
working code is in the above commit. Not too long, but too long for MD. */
yield return ParseXmlFragment(xmlFragment);
...}
}
Foo ParseXmlFragment(string xmlFragment)
{
Foo newFoo = new Foo();
try{//xmlreader here to parse fragment}
catch(ex)
{
// handle ex if possible here. If not possible, you now have the complete text of the unparsable fragment, which you can correct and try again.
throw; // if you want to halt execution, or you can continue
}
}