產生xmldocument 資料量大 記憶體不足問題 |
答題得分者是:aftcast
|
isthatu1999
一般會員 ![]() ![]() 發表:3 回覆:3 積分:1 註冊:2010-06-29 發送簡訊給我 |
最近user端來份公文 原本轉給他們的資料text 要改傳xml格式
小弟 用了xmldocment元件 來產製 結果程式寫好 實際去run資料 不得了 幾十萬筆資料 居然搞到記憶體不足 感覺節點一直新增時就不斷的耗用記憶體 最後出現out of memory訊息 不知是我寫法有問還是還有其他方法可以解決 程式範例如下 直接迴圈跑2000次 * 20明細 值都隨便塞 (每個月實際的應該高過這個) 結果記憶體不斷的飆高 最後爆了 想說有一個好用的xmldocment 元件 特地使用使用delphi7來用 實在很不想走那種自己塞tag麻煩要命的寫法 不知有各位有更好得解決方法嗎? 範例: 可以順便觀察程式記憶體一直爆衝 procedure TFinsXML.Button2Click(Sender: TObject); var i,j,k,m,n:integer; inpatient:IXMLNode; tdata:IXMLNode; ddata:IXMLNode; dhead:IXMLNode; dbody:IXMLNode; pdata:IXMLNode; t:array[1..32] of IXMLNode; {總表定義節點} d:array[1..103] of IXMLNode; {主檔} p:array[1..22] of IXMLNode; {明細} begin // 頁面放一顆xmldocment元件了 這段copy下來就應改可以run // 再放一個memo1 讀產製的xml XMLDocument1.XML.Clear; XMLDocument1.Active := True; XMLDocument1.Version := '1.0'; XMLDocument1.Encoding := 'Big5'; inpatient :=XMLDocument1.AddChild('inpatient'); tdata := _inpatient.AddChild('tdata'); for j:=1 to 32 do // summary begin t[j] := tdata.AddChild('t' inttostr(j)); t[j].Text := widestring(inttostr(j)); end; for i:=1 to 2000 do //給跑2000主檔筆資料 begin // main_data ddata := _inpatient.AddChild('ddata'); dhead := ddata.AddChild('dhead'); d[1] := dhead.AddChild('d1'); d[1].Text := widestring('d1'); d[2] := dhead.AddChild('d2'); d[2].Text := widestring('d2'); dbody:= ddata.AddChild('dbody'); for k:=2 to 103 do begin d[k] := dbody.AddChild('d' inttostr(k)); d[k].Text := widestring('d' inttostr(k)); end; for n:=1 to 20 do // 每筆主檔給run 20筆 明細 begin pdata := dbody.AddChild('dpdata'); for m:=1 to 22 do // sub_data begin p[m] := pdata.AddChild('p' inttostr(k)); p[m].Text := widestring('p' inttostr(k)); end; end; end; XMLDocument1.SaveToFile('c:\a.xml'); Memo1.Clear; Memo1.Lines.LoadFromFile('c:\a.xml'); end; |
aftcast
站務副站長 ![]() ![]() ![]() ![]() ![]() 發表:81 回覆:1485 積分:1763 註冊:2002-11-21 發送簡訊給我 |
|
isthatu1999
一般會員 ![]() ![]() 發表:3 回覆:3 積分:1 註冊:2010-06-29 發送簡訊給我 |
這範例跑2000次 出來是29M XML行數1千2百萬行 (自己都 嚇一跳)
不過USER每個月大概6000案件 應該是這3倍 後來我已經解決了......... 就是這種大量資料要轉成XML時 不能直接以1個xmldocument來一次跑底 光建立節點就會記憶體就爆掉 所以我的作法是拆解 xml 分批建立XMLDocument 再釋放 ..再建立.... 例如跑500筆時 就用stringlist 承接起來 aList.Text:= aList.Text XMLDocument.XML.Text; 然後 釋放掉原本的 XMLDocument XMLDocument.XML.Clear; XMLDocument.Destroy; XMLDocument := nil; 迴圈 中再 create XMLDocument := TXMLDocument.create(self); XMLDocument.XML.Clear; XMLDocument.Options:= XMLDocument.Options [doNodeAutoIndent]; XMLDocument.Active := True; XMLDocument.Version := '1.0'; XMLDocument.Encoding := 'Big5'; xmldocumet 繼續接資料 stringList 再後面繼續接資料 只是注意到接資料時把上層tag去掉 XMLDocument.XML.Delete(XMLDocument.XML.Count-1); XMLDocument.XML.Delete(1); XMLDocument.XML.Delete(0); 最後迴圈完成後 stringList再把最外層的ending tag 補上 aList.Lines.add(''); aList.存檔即可!! 這樣觀察記憶體就不會爆衝了 程式之前衝到 記憶體1.6g 程式改了後就在100m-200m間上上下下 以上。 ===================引 用 aftcast 文 章=================== 好奇的請問一下a.xml檔案最後是多大? 或者你客戶轉成xml後,那個檔有多大? |
aftcast
站務副站長 ![]() ![]() ![]() ![]() ![]() 發表:81 回覆:1485 積分:1763 註冊:2002-11-21 發送簡訊給我 |
嗯,我想若你的檔案大到這種程度,若是我,可能考慮使用File Mapping的技術(查msdn)。這樣就不用一直放在記憶體裡(包含list)。
一直的往檔案裡寫一段,然後release 物件 (就如你現在做的,差別在不放在list裡)。 我想那樣的寫法就算文件再大,都不會是問題,效能應該也是極好才是! 不過,你目前的做法也很不錯了 :) 參考參考
------
蕭沖 --All ideas are worthless unless implemented-- C++ Builder Delphi Taiwan G+ 社群 http://bit.ly/cbtaiwan |
isthatu1999
一般會員 ![]() ![]() 發表:3 回覆:3 積分:1 註冊:2010-06-29 發送簡訊給我 |
|
sryang
尊榮會員 ![]() ![]() ![]() ![]() ![]() ![]() 發表:39 回覆:762 積分:920 註冊:2002-06-27 發送簡訊給我 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |