4

次のように、ストリームとして読み取る必要がある非常に大きな 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;
            }
        }
    }
}

処理の途中で、無効な char 例外が発生します。

' ', hexadecimal value 0x19, is an invalid character. Line 655, position 45.

try-catch 内で return を生成することが許可されていない場合、エラーが発生した場合に、現在の Xml ドキュメントの処理を単純に中止する (および列挙を完了する) 良い方法は何ですか?

try/finally は良くありません - 例外が IEnumerable 全体の処理を中断するからです。

ファイルに対して前処理を実行できません。

4

2 に答える 2

0

私はちょうど同じことを扱っていました。これが古いことは知っていますが、参考のためにここに載せると思いました。

要旨を載せるつもりでしたが、GitHubのコミットを見た方が参考になると思います。

https://github.com/DewJunkie/Log2Console/commit/fb000c0a97c6762b619d213022ddc750bd9254ae winmerge を使用して以前のバージョンを比較すると、変更の全体像がより明確になります。

try catch 内で yield を返すことはできませんが、解析された単一のインスタンスを返す別の関数を使用することはできます。try catch はその 2 番目の関数にあります。正規表現を使用して、ログを単一のレコードに分割しました。大きなファイルであっても、1 つのレコードが数 KB のバッファーに収まると思います。RegEx にはいくらかのオーバーヘッドがあることも想像できますが、私の主な懸念はデータの損失でした。

私は実際にパーサーの作成に数時間を費やしていました。テストを行っているときに、パーサーの本質はこの正規表現であり、実際には残りの部分は必要ないことに気付きました。

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
   }
}
于 2016-05-15T11:17:36.607 に答える