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 的处理。

我无法对文件执行任何预处理。

XmlReader 异常处理 - 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
   }
}
相关文章: