2012-02-18 4 views
2

GPS座標(GPX)のコレクションであるJavaを使用してXMLファイルを作成しようとしています。私がアンドロイドデバイスから座標を受け取るたびに(毎秒約1回)、結果を既存のXMLファイルに追加する必要があります。私が探している出力は、trkpt要素を繰り返し項目として以下に示しています。問題は、新しいtrkptをtrksegの親要素の内側に配置する必要があるため、ファイルの最後に新しいtrkptを追加するだけでは問題がないことです。Javaを使用して大きなXMLファイルに子要素を追加する方法は?

これまでのところ、私は2つの異なるAPI、SIMPLEXMLとJDOMを試しました。 SIMPLEXMLでは、JDOMに切り替えたので、既存のファイルに子要素を追加する方法を理解できませんでした。 JDOMでは、以下に示すようにtrkpt要素を追加することができましたが、ファイルが大きくなってすぐにプログラムのユーザーインターフェイスが遅くなりました。 JDOMでは、SAXBuilderを使用してファイルを再度開いて追加していました。私は、この問題は、新しい要素を追加してファイルを書き換える前に、ファイル全体をメモリに再現しなければならないことだったと思います。したがって、ファイルが大きくなればなるほど、デバイス上で操作が要求されます。新しいデータを書き込む前に、ファイル全体を調べたりコピーしたりしないという解決策が必要です。 JavaまたはJava用APIを使用してこれを実現する効率的な方法はありますか?助けてくれてありがとう!

<?xml version="1.0" encoding="UTF-8"?> 
<gpx xmlns="http://www.topografix.com/GPX/1/1"> 
     <trk> 
      <trkseg> 
       <trkpt lon="9.860624216140083" lat="54.9328621088893"> 
        <ele>228.0</ele> 
       </trkpt> 
       <trkpt lon="9.860624216140100" lat="54.9328621088754"> 
        <ele>234.0</ele> 
       </trkpt> 
       <trkpt lon="9.860624216140343" lat="54.9328621088678"> 
        <ele>227.0</ele> 
       </trkpt> 
      </trkseg> 
     </trk> 
</gpx> 
+0

常に同じ方法でデータを追加していますか?次に、ファイルを行単位で読み込み、行をXMLにとらわれない方法で追加することを検討してください。結果が有効なXMLである限り –

+1

代わりにプレーンファイルにデータを追加して、ファイル全体をXMLに後で変換することはできますか?それともバッチで変換するのでしょうか? XMLを継続的に更新しようとすると、人生を不必要に難しくするように思えます! ;-) – DNA

+0

私はあなたの質問は、クライアント側の処理(アンドロイド)ではなく、サーバー側の処理、正しいと思いますか? – home

答えて

0

I/Oに関して、特に反復的な方法でファイルを開閉/再オープンするときは、常にボトルネックがあります。

DOMハンドラは、ファイルを開くたびにツリー構造全体を作成しますが、そのツリーを変更するときは非常に効果的です。

まず最初に、すべてのティックでファイルを開いたり、変更したり、保存したりする必要がありますか?そうでない場合は、ファイルのDOMをメモリに保持し、XMLへの参照を変更します。ユーザーがアプリを終了するかビューを終了したら保存します。

ティックごとにファイルを保存する必要がある場合でも、メモリにDOMを保存しておき、毎回ティックごとにディスクに保存するだけです。

目盛りごとにファイルを開く/保存する/再開く必要がある場合は、XMLライブラリを使用しないでください。標準のFileWriterなどを手動で使用して内容を手動で変更してください。ファイルが本当に大きくなった場合、パフォーマンスを維持するのは難しいでしょう。

+0

必ずしもすべてのティックでファイルに保存する必要はありません。書き込まれるのを待っている間にデータを失う大きな可能性がない限り。私は、データの量がGBの範囲に入る可能性があるので、アプリケーションを終了するときの節約が問題になるかもしれないと言及するべきだと思います。 – Ferrari692

+0

@ Ferrari692ええと、そのサイズのDOMオブジェクトをメモリに保持してはいけません。そのサイズのファイル全体(チャンクまたは非XML)を解析する以外の方法を使用することを検討してください。 –

0

これはSAXの完璧なアプリケーションのように聞こえます(パッケージorg.xml.saxにあります)。 XMLへのアクセスと操作のためのストリーミングAPIです。 SAXは、検出したすべての要素のイベントを生成します。これにより、ファイルを大規模なメモリ内のツリーに解析することなく、ファイルを新しいファイルにコピーできます。入力ファイルの最後に達したら、最後のタグを<trkseg>で処理する前に、新しい要素を追加してください。

もちろん、このファイルを1秒ごとに書き直すというアプローチは、疑問を呈します。より大きなセグメントに情報をバンドルできますか?特定の間隔(10/30/60秒ごと)で単一のファイルに情報をダンプして1つのファイルにまとめることができます。

+0

私は、情報をバンドルし、より大きな間隔を使用する問題はありません。私はSAXの使用方法について検討します。 – Ferrari692

0

ここで述べたように簡単なのであれば、RandomAccessFileを使用して、ファイル長から数バイト(ルート終了タグの直前)を探してそこに上書きしてください。

+0

興味深い。私はそれを試してみる必要があります。 – Ferrari692

0

xmlファイルを3つに分割することをお勧めします。

head.xml

<?xml version="1.0" encoding="UTF-8"?> 
<gpx xmlns="http://www.topografix.com/GPX/1/1"> 
    <trk> 
     <trkseg> 

体。

List<InputStream> list = new ArrayList<InputStream>(3); 
list.add(new FileInputStream("head.xml")); 
list.add(new FileInputStream("body.xml")); 
list.add(new FileInputStream("tail.xml")); 
InputStream xmlStream = new SequentialInputStream(Collections.enumeration(list)); 
:XML

<trkpt lon="9.860624216140083" lat="54.9328621088893"> 
    <ele>228.0</ele> 
</trkpt> 
<trkpt lon="9.860624216140100" lat="54.9328621088754"> 
    <ele>234.0</ele> 
</trkpt> 
<trkpt lon="9.860624216140343" lat="54.9328621088678"> 
    <ele>227.0</ele> 
</trkpt> 

tail.xml今

 </trkseg> 
    </trk> 
</gpx> 

新しいデータを取得するたびに、単に以下のようにxmlファイルを使用したSequenceInputStreamを読み取ること

をbody.xmlするためにそれを追加

関連する問題