3

XMLStreamReader を使用して xml タグのバイト オフセットを正確に収集する方法はありますか?

ランダム アクセスが必要な大きな xml ファイルがあります。すべてをデータベースに書き込むのではなく、XMLStreamReader を使用して 1 回実行し、重要なタグのバイト オフセットを収集してから、RandomAccessFile を使用して後でタグの内容を取得できるようにしたいと考えています。

XMLStreamReader には、文字オフセットを追跡する方法がないようです。代わりに、読み取られたバイト数を追跡​​するリーダーに XmlStreamReader をアタッチすることをお勧めします (たとえば、 apache.commons.ioによって提供される CountingInputStream )。

例えば:

CountingInputStream countingReader = new CountingInputStream(new FileInputStream(xmlFile)) ;
XMLStreamReader xmlStreamReader = xmlStreamFactory.createXMLStreamReader(countingReader, "UTF-8") ;


while (xmlStreamReader.hasNext()) {
    int eventCode = xmlStreamReader.next();

    switch (eventCode) {
        case XMLStreamReader.END_ELEMENT :
            System.out.println(xmlStreamReader.getLocalName() + " @" + countingReader.getByteCount()) ;
    }

}
xmlStreamReader.close();

残念ながら、上記のコードは複数のタグに対して同じバイト オフセットを出力するため、何らかのバッファリングが行われているに違いありません。xml ファイルのバイト オフセットを追跡するより正確な方法はありますか (理想的には、適切な xml 解析を放棄することはありません)。

4

6 に答える 6

2

XMLStreamReader (または XMLEventReader を使用する場合は XMLEvent.getLocation()) で getLocation() を使用できますが、信頼性が低く正確ではないことをどこかで読んだことを覚えています。そして、開始位置ではなく、タグのエンドポイントを提供しているようです。

ファイル内のタグの位置を正確に知りたいという同様のニーズがあり、必要なレベルの位置精度を提供することを保証するパーサーがあるかどうかを確認するために他のパーサーを調べています。

于 2010-07-05T02:24:18.770 に答える
1

実際の入力ストリームの周りにラッパー入力ストリームを使用して、実際の I/O 操作のためにラップされたストリームを延期するだけで、現在のオフセットを取得するためのさまざまなコードを使用して内部カウント メカニズムを維持できますか?

于 2010-07-04T23:56:41.090 に答える
1

残念ながら、Aalto は LocationInfo インターフェイスを実装していません。

最新の Java VTD-XML ximpleware 実装 (現在はsourceforgeまたはgithubの 2.11 ) は、IReader 実装の getChar() メソッドを呼び出すたびに、バイト オフセットを維持するコードを提供します。

VTDGen.java および VTDGenHuge.java 内で、さまざまな文字エンコーディングの IReader 実装を使用できます。

IReader の実装は、次のエンコーディング用に提供されています

ASCII;
ISO_8859_1
ISO_8859_10
ISO_8859_11
ISO_8859_12
ISO_8859_13
ISO_8859_14
ISO_8859_15
ISO_8859_16
ISO_8859_2
ISO_8859_3
ISO_8859_4
ISO_8859_5
ISO_8859_6
ISO_8859_7
ISO_8859_8
ISO_8859_9
UTF_16BE
UTF_16LE
UTF8;   
WIN_1250
WIN_1251
WIN_1252
WIN_1253
WIN_1254
WIN_1255
WIN_1256
WIN_1257
WIN_1258

getCharOffset() メソッドを使用して IReader を更新し、VTDGen および VTDGenHuge クラスのオフセット メンバーに charCount メンバーを追加して実装し、各 IReader 実装の getChar() および skipChar() 呼び出しごとにそれをインクリメントすることで開始できます。ソリューションの。

于 2014-04-27T18:02:16.970 に答える
0

別の選択肢を見つけたと思います。ブロックを次のように置き換えるswitchと、終了要素タグの直後の位置がダンプされます。

        switch (eventCode) {
        case XMLStreamReader.END_ELEMENT :
            System.out.println(xmlStreamReader.getLocalName() + " end@" + xmlStreamReader.getLocation().getCharacterOffset()) ;
        }

また、このソリューションでは、終了タグの実際の開始位置を手動で計算する必要があり、外部 JAR ファイルを必要としないという利点があります。

データ管理の小さな不一致を突き止めることはできませんでしたが (これは、私の を初期化した方法に関係していると思いますXMLStreamReader)、読者がコンテンツを移動するにつれて、場所が一貫して増加するのを常に確認しました。

お役に立てれば!

于 2010-07-05T01:28:30.870 に答える