batやvbsなど、プログラムを書いてくれる方を探しています。
謝礼は100~500pt、完全解答をお願いします。
たとえば、電話帳を記載したxmlファイルが数種類あります。このファイルを別のプログラムで処理するには重すぎるとします。
サイズだけを基準にぶった切ると処理をするときにxmlの整合性が崩れるので処理ができないという問題が出ます。そこで、整合性を維持したままxmlファイルを分割したいです。batなどのファイルで。
条件
1. 毎回処理する対象のXMLの形式はおおまかに同じ
2. XML は、次のようになっている。
addressbooktokyo.xmlの中身
<xml version="1.0" encoding="utf-8"?>
<任意の一行、定型句>
<header>
<各種ヘッダー情報、たとえば地域などファイルによって微妙に違う>
</header>
<body>
<person>
<name>山田さん</name>
<phone>0123456789</phone>
</person>
膨大な繰り返し・・・
</body>
</xml>
補足に手順イメージを記載しました。
手順イメージ
1. ファイルの初回読み込み時に<xml宣言>プラス<header>から</header>を読み込んで一時的にどこかにキープする(これがヘッダ部分)。
2. <body>内を読み込みながら、output1.xmlファイルに各行を書き出す。
3. 繰り返しが1000行を超えて「かつ」</person>の行を読み込んだときに、</body></xml>を付け足してそのファイルは終了、が、繰り返しは継続
4. 繰り返しを継続するが、出力先はoutput2.xmlにインクリメントし、初回のみ、手順1のヘッダ部分を付け加えて、以下bodyを繰り返す
という流れにできないか、と考えています。
ファイル末尾に至るときにどう処理するかはちょっとした工夫が要るかもしれません。
FileSystemObject でサポートしているのは S-JIS か unicode なので、
ちょっと処理が複雑なのと、処理が遅いかもしれませんが ADODB.stream で
UTF-8 として処理しています。
また、できればきちんと XML として構文処理したほうがよいと思いますが、
例示されたサンプルは MSXML2.DOMDocument で読み込めなかったので、
文字列処理としています。
Option Explicit '//----------------------------------- Const FILE_PATH = "D:\Data\Data.xml" '// 処理ファイル名 Const DIV_SIZE = 1000 '// 1ファイルの分割行数 '//----------------------------------- Dim inXML Set inXML = CreateObject("ADODB.Stream") inXML.Type = 2 '// 1:バイナリデータ 2:テキストデータ inXML.Charset = "UTF-8" inXML.Open inXML.LoadFromFile FILE_PATH '// header(body まで) 読込 '//----------------------------------- Dim headerCount Dim headerPart Dim readOneLine Do While inXML.EOS = False readOneLine = inXML.ReadText(-2) headerPart= headerPart & readOneLine & vbNewLine headerCount = headerCount + 1 If InStr( UCase( readOneLine ), "<BODY>" ) > 0 Then Exit Do Loop '//----------------------------------- Dim outXML Set outXML = CreateObject("ADODB.Stream") outXML.Type = 2 '// 1:バイナリデータ 2:テキストデータ outXML.Charset = "UTF-8" '// person データ読込 '//----------------------------------- Dim divFileCount Dim fileCount Dim dstXML Dim exportFile exportFile = "" Dim outContents Do While inXML.EOS = False '// 初期化処理 If exportFile = "" Then fileCount = fileCount + 1 exportFile = "outFile" & fileCount & ".xml" outContents = HeaderPart divFileCount = headerCount End If readOneLine = inXML.ReadText(-2) outContents = outContents & readOneLine & vbNewLine divFileCount = divFileCount + 1 '// ファイル出力 If divFileCount > DIV_SIZE Then If InStr( UCase( readOneLine ), "</PERSON>" ) > 0 Then outContents = outContents & "</body>" & vbNewLine outContents = outContents & "</xml>" & vbNewLine outXML.Open outXML.WriteText outContents, 1 outXML.SaveToFile exportFile, 2 outXML.Close exportFile = "" End If End If Loop '// 最後のファイル出力 If divFileCount <> headerCount Then outXML.Open outXML.WriteText outContents, 1 outXML.SaveToFile exportFile, 2 outXML.Close End If inXML.Close
http://trwtnb.blogspot.jp/2009/10/vbscriptutf-8.html
http://www.atmarkit.co.jp/fxml/rensai/msxml01/msxml03.html
FileSystemObject でサポートしているのは S-JIS か unicode なので、
ちょっと処理が複雑なのと、処理が遅いかもしれませんが ADODB.stream で
UTF-8 として処理しています。
また、できればきちんと XML として構文処理したほうがよいと思いますが、
例示されたサンプルは MSXML2.DOMDocument で読み込めなかったので、
文字列処理としています。
Option Explicit '//----------------------------------- Const FILE_PATH = "D:\Data\Data.xml" '// 処理ファイル名 Const DIV_SIZE = 1000 '// 1ファイルの分割行数 '//----------------------------------- Dim inXML Set inXML = CreateObject("ADODB.Stream") inXML.Type = 2 '// 1:バイナリデータ 2:テキストデータ inXML.Charset = "UTF-8" inXML.Open inXML.LoadFromFile FILE_PATH '// header(body まで) 読込 '//----------------------------------- Dim headerCount Dim headerPart Dim readOneLine Do While inXML.EOS = False readOneLine = inXML.ReadText(-2) headerPart= headerPart & readOneLine & vbNewLine headerCount = headerCount + 1 If InStr( UCase( readOneLine ), "<BODY>" ) > 0 Then Exit Do Loop '//----------------------------------- Dim outXML Set outXML = CreateObject("ADODB.Stream") outXML.Type = 2 '// 1:バイナリデータ 2:テキストデータ outXML.Charset = "UTF-8" '// person データ読込 '//----------------------------------- Dim divFileCount Dim fileCount Dim dstXML Dim exportFile exportFile = "" Dim outContents Do While inXML.EOS = False '// 初期化処理 If exportFile = "" Then fileCount = fileCount + 1 exportFile = "outFile" & fileCount & ".xml" outContents = HeaderPart divFileCount = headerCount End If readOneLine = inXML.ReadText(-2) outContents = outContents & readOneLine & vbNewLine divFileCount = divFileCount + 1 '// ファイル出力 If divFileCount > DIV_SIZE Then If InStr( UCase( readOneLine ), "</PERSON>" ) > 0 Then outContents = outContents & "</body>" & vbNewLine outContents = outContents & "</xml>" & vbNewLine outXML.Open outXML.WriteText outContents, 1 outXML.SaveToFile exportFile, 2 outXML.Close exportFile = "" End If End If Loop '// 最後のファイル出力 If divFileCount <> headerCount Then outXML.Open outXML.WriteText outContents, 1 outXML.SaveToFile exportFile, 2 outXML.Close End If inXML.Close
http://trwtnb.blogspot.jp/2009/10/vbscriptutf-8.html
http://www.atmarkit.co.jp/fxml/rensai/msxml01/msxml03.html
上記のコメントで書いた UNICODE にすれば・・・、という話は単にデータの文字コードを変えるだけでなく、処理を FSO を使うように変更すればという意味で書きました。
ただそれでも2.3GBというファイルを処理するというのは、想像していませんでしたが。
この規模のファイル処理を頻繁にするのであれば、スクリプト処理ではちょっと限界がありそうです。
データの運用フロー(入力から出力まで)が不明ですが、その規模のファイル(データ)を処理するのであれば、XML ではなくODBS を使いたい気がしました。
600GBのファイルはなんとか処理できているのが確認できました。
さすがにこの規模のファイルを扱うことは多くないので、許容範囲かと思います。現状、2.3GBのファイルは機械的に分割して、手動でヘッダとフッタをつけて処理しました。
はてなで別の質問をするかもしれませんが、最初に機械的な分割をして、連番の前と後ろのファイルを参照しながらxmlの整合性をとっていく方法が処理スピードが早いかもしれません。
今回の質問はこれにて終了しようと思います。ぶっちぎりのベストアンサーですありがとうございました。
上記のコメントで書いた UNICODE にすれば・・・、という話は単にデータの文字コードを変えるだけでなく、処理を FSO を使うように変更すればという意味で書きました。
2012/12/13 11:57:49ただそれでも2.3GBというファイルを処理するというのは、想像していませんでしたが。
この規模のファイル処理を頻繁にするのであれば、スクリプト処理ではちょっと限界がありそうです。
データの運用フロー(入力から出力まで)が不明ですが、その規模のファイル(データ)を処理するのであれば、XML ではなくODBS を使いたい気がしました。
600GBのファイルはなんとか処理できているのが確認できました。
2012/12/13 13:57:21さすがにこの規模のファイルを扱うことは多くないので、許容範囲かと思います。現状、2.3GBのファイルは機械的に分割して、手動でヘッダとフッタをつけて処理しました。
はてなで別の質問をするかもしれませんが、最初に機械的な分割をして、連番の前と後ろのファイルを参照しながらxmlの整合性をとっていく方法が処理スピードが早いかもしれません。
今回の質問はこれにて終了しようと思います。ぶっちぎりのベストアンサーですありがとうございました。