2016-06-19 4 views
0

選択したXMLファイルを分割するJavaプログラムを作成しようとしています。Javaを使用したBIGファイルのXML分割

XMLファイルのデータサンプル:お尻に

<EmployeeDetails> 
<Employee> 
<FirstName>Ben</FirstName> 
</Employee> 
<Employee> 
<FirstName>George</FirstName> 
</Employee> 
<Employee> 
<FirstName>Cling</FirstName> 
</Employee> 
<EmployeeDetails> 

というように、私はこの250メガバイトXMLファイルのアリを持って、それは常に痛みそれを外部プログラムを開いて、手動で読めることができるようにそれを分割します他のもの(すべてのラップトップ/デスクトップがそのような大きなファイルを開くことはできません)。そこで、私はこの機能を持つJavaプログラムを作成することにしました: - XMLファイルを選択してください(すでに完了しています) - 例えば、#のタグに基づいてファイルを分割します(現在のファイルには100kのタグがあります。例:ファイルごとに10kファイルを分割する - ファイルを分割する(すでに完了している)

2番目のタスクを実行するにはどうすればよいでしょうか? -4日は、私はおそらくこれを行うことができますどのように確認するか(それはもちろん、私の心の中で)それも可能である。

どれレスポンスが理解されるであろう。

乾杯、をGrimm。

+0

Javaの場合、ファイル全体がメモリに読み込まれるDOM(ドキュメントオブジェクトモデル)が2つあります。実装するのが少しシンプルになりますが、妥当な量のメモリが必要になります。プログラムがそれ以上のことをしていなければ1GBのJVMで十分です。 SAX(ストリーミング)モデルは100GBになってもファイルを処理できます。ファイルは一度に少しずつ読み込まれ、たとえば新しいタグが見つかるとコールバックが発生します。 [この記事](http://stackoverflow.com/questions/6828703/what-is-the-difference-between-sax-anddom)にもう少し詳しく説明します。 – stdunbar

+0

3番目の選択肢もあります.XSLT変換を実行します。 –

+0

そして第4の選択肢:StAX。 – biziclop

答えて

0

簡単な解決方法があります。 XMLが常にこのような改行を持つ場合、XML処理は必要ありません。

Path originalPath = Paths.get("... .xml"); 
try (BufferedReader in = Files.newBufferedReader(originalPath, StandardCharsets.UTF_8)) { 
    String line = in.readLine(); // Skip header line(s) 

    line = in.readLine(); 
    for (int fileno; line != null && !line.contains("</EmployeeDetails>"); ++fileno) { 
     Path partPath = Paths.get("...-" + fileno + ".xml"); 
     try (PrintWriter out = new PrintWriter(Files.newBufferedWriter(partPath, 
       StandardCharsets.UTF_8))) { 
      int counter = 0; 
      out.println("<EmployeeDetails>"); // Write header. 
      do { 
       out.println(line); 
       if (line.contains("</Employee>") { 
        ++counter; 
       } 
       line = in.readLine(); 
      } while (line != null && !line.contains("</EmployeeDetails>") 
        && counter < 1000); 
      out.println("</EmployeeDetails>"); 
     } 
    } 
} 
+0

これはかなりうまく動作しますが、上のコメントで私の同じ問題であるように見えますが、「例外のメイン」java.lang.OutOfMemoryError:Javaヒープspace " – Grimmjow

+0

これは奇妙なことですが、PrintWriterは残念ながらカーペットの下で例外を掃除するので、BufferedWriterだけを使ってみてください。あなたは横にある行を読んで何かをしますか? –

+0

別の考え方:xmlのgz圧縮を 'xxx.xml.gz'に使い、' new InputStreamReader(new GZipInputStream(... ')を使います。 –

1

ドキュメントRのルート要素にXという名前の子が多数存在すると仮定すると、次のXSLT 2.0変換はN番目のX要素ごとにファイルを分割します。

<t:transform xmlns:t="http://www.w3.org/1999/XSL/Transform" 
    version="2.0"> 
    <t:param name="N" select="100"/> 
    <t:template match="/*"> 
    <t:for-each-group select="X" 
         group-adjacent="(position()-1) idiv $N"> 
     <t:result-document href="{position()}.xml"> 
     <R> 
      <t:copy-of select="current-group()"/> 
     </R> 
     </t:result-document> 
    </t:for-each-group> 
    </t:template> 
</t:transform> 

あなたは(メモリ内のソースツリーを構築せずに)ストリーミングモードでこれを実行したい場合は、(a)は<xsl:mode streamable="yes"/>を追加し、(b)はXSLT 3.0プロセッサを使用してそれを実行します(サクソン-EEまたはExselt )。

+0

これは期待どおりに動作しています。今私はあなたのコメントと下の2つのオプションがあります。しかし明らかに2つの答えをチェックすることは不可能です。 – Grimmjow

関連する問題