我将一些数据存入xml文件,大约有10万条。使用delphi的XMLDocument来操作。读取和写入都需要大约5分钟左右,非常慢。请问有没有什么方法可以极大提高速度?我不想用数据库保存这些数据如果实在不行的话,如果我用ini文件保存数据,能够显著提高读写速度吗?数据是标准的树型结构。没有google到可用的解决方案,求csdn高人现身
解决方案 »
- windows 7旗舰版 64位 delphi7/xe能正常开发吗?
- 如何编程登录进入远程系统并执行命令,已知用户名和密码
- 本人想做一个像mp3共享软件酷狗那样的p2p软件,请问用Delphi实现有困难吗?
- 帮看代码,关于是否联网
- 自定义procedure问题
- 如何把一段全角的网址转换成半角的?谢谢---急
- 10分问一个更严肃的问题,欢迎灌水!
- 我想用SQL语句...我在那里写呢?
- 菜鸟求教,关于自定义纸张 的问题
- 请问d7自带的控件哪个根据财务数据生成折线图效果最好
- delphi2007安装后进入时需要注册码
- 免费没有任何限制的最强大的短信控件(收发短信),支持WAVECOM模块,D6开发,提供给广大D的朋友
但是
1.我不想用数据。
2.数据需要全部进入内存流,进行压缩加密等处理,用sax好像也不是办法,代码比较麻烦现在想改用ini文件保存读取,不知道速度是否会快很多
<root>
<root1>
<node1>??</node1>
<node2>?????</node2>
<node3>
<leaf1>1.23323</leaf1>
<leaf2>1.23234323</leaf2>
<leaf2>5.2334323</leaf3>
<leaf4>4.5443</leaf4>
........上万条数据... </node3>
</root1>
<root2>
..............
</root2>
</root>
xml最多到六层节点,在一个循环里读写数据,主要是读取leaf的数据太慢,在IBMT60,1.5G内存机器上,读取三万条数据大概要10秒。而数据量可能会超过30万条!!!要求不能使用数据库,代码量要少,因为需要存大量的复杂记录类型变量到文件。
开始考虑过内存流的方法,但记录类型包含不定长string,包含二维的动态数组,在csdn上没有找到合适的方法写内存流。现在用xml可以实现存取,但速度实在无法忍受。再加上其它一些函数运算,控件动态生成,这个速度跟蜗牛似的。
procedure TForm1.Button1Click(Sender: TObject);
var inifile:Tinifile;
i:integer;
begin
inifile:=tinifile.Create('d:\1.ini');
//gettime
showmessage('ss');
for i:=0 to 26000 do
begin
inifile.WriteInteger ('logdata','data'+inttostr(i),i);
end;
inifile.Destroy;
showmessage('ee');
end;
Access就OK了~也不用带什么库的
PXMLNode = ^TXMLNode;
TXMLNode = record
Name: string;
Value: string;
Parent: PXMLNode;
Attr: array of PXMLNode;
Child: array of PXMLNode;
end;function ParseXML(const XMLText: string; Root: PXMLNode): Boolean; function GetElementName(var P: PChar; var IsEndElement: Boolean): string;
var
S: PChar;
begin
Result := '';
while not (P^ in ['<', #0]) do Inc(P);
if P^ = '<' then Inc(P);
IsEndElement := P^ = '/';
{if IsEndElement then
begin
Inc(P);
while not (P^ in ['>', #0]) do Inc(P);
Inc(P);
Result := GetElementName(P, IsEndElement);
Exit;
end; }
if P^ = '/' then Inc(P);
if P^ = #0 then Exit;
S := P;
while not (P^ in ['>', #0]) do Inc(P);
SetString(Result, S, P - S);
Result := Trim(Result);
if P^ = '>' then Inc(P);
end; procedure OffsetElementEnd(var P: PChar);
begin
while not (P^ in ['<', #0]) do Inc(P);
if P^ = '<' then Inc(P);
if P^ = '/' then Inc(P);
if P^ = #0 then Exit;
while not (P^ in ['>', #0]) do Inc(P);
if P^ = '>' then Inc(P);
end; function GetNextElemntName(P: PChar): string;
var
S: PChar;
begin
Result := '';
while not (P^ in ['<', #0]) do Inc(P);
if P^ = '<' then Inc(P);
if P^ = '/' then Inc(P);
if P^ = #0 then Exit;
S := P;
while not (P^ in ['>', #0]) do Inc(P);
SetString(Result, S, P - S);
Result := Trim(Result);
end; function GetContent(P: PChar): string;
const
IgnoreChar = [#13, #10, #9, '&', '"', #0];
var
S: PChar;
begin
while P^ in ['"', #0] do Inc(P);
S := P;
while not (P^ in ['<', #0]) do Inc(P);
while P^ in IgnoreChar do Dec(P);
SetString(Result, S, P - S);
Result := Trim(Result);
end; function GetXMLNode(Parent: PXMLNode; var XMLSrc: PChar; var XMLSize: Integer): Boolean;
var
T, NodeName: string;
L: Integer;
Node: TXMLNode;
Child: PXMLNode;
IsEnd: Boolean;
begin
Result := False;
FillChar(Node, SizeOf(Node), 0);
NodeName := GetElementName(XMLSrc, IsEnd);
if IsEnd then
begin
Result := GetXMLNode(Parent.Parent, XMLSrc, XMLSize);
Exit;
end; if NodeName <> '' then
begin
Child := AllocMem(SizeOf(TXMLNode));
SetLength(Child.Child, 0);
Child^.Name := NodeName;
Child^.Parent := Parent;
if Assigned(Parent) then
begin
L := Length(Parent^.Child);
SetLength(Parent^.Child, L + 1);
Parent^.Child[L] := Child;
end;
T := GetNextElemntName(XMLSrc);
if SameText(T, Child^.Name) then
begin
Child^.Value := GetContent(XMLSrc);
OffsetElementEnd(XMLSrc);
Result := GetXMLNode(Parent, XMLSrc, XMLSize);
end else
Result := GetXMLNode(Child, XMLSrc, XMLSize)
end;
end;var
XMLSrc: PChar;
XMLSize: Integer;
begin
XMLSrc := PChar(XMLText);
XMLSize := Length(XMLText);
Result := XMLSize > 0;
if not Result then Exit;
Result := GetXMLNode(Root, XMLSrc, XMLSize);
end;
分成多个XML文件
多线程操作其实还是数据库
const
MAXBUF_NODES = 10240;type
TXMLStr = record
ptr: PChar;
len: Integer;
end; PXMLNode = ^TXMLNode;
TXMLNode = record
Name: TXMLStr;
Value: TXMLStr;
Parent: PXMLNode;
Child: array of PXMLNode;
end; PXMLDataArray = ^TXMLDataArray;
TXMLDataArray = record
Nodes: array [0..MAXBUF_NODES - 1] of TXMLNode;
next: PXMLDataArray;
end; PXMLData = ^TXMLData;
TXMLData = record
Root: PXMLNode;
XMLData: TXMLStr;
BufCount: Integer;
IdleNodeBuffers: PXMLNode;
NodeBuffers: PXMLDataArray;
end;procedure TrimStr(var V: TXMLStr);
var
P: PChar;
begin
while V.ptr^ = ' ' do
begin
Inc(V.ptr);
Dec(V.len);
end;
if V.len > 0 then
begin
P := V.ptr + V.Len - 1;
while P^ = ' ' do
begin
Dec(P);
Dec(V.len);
end;
end;
end;function GetString(V: TXMLStr): string;
begin
if V.len > 0 then
begin
TrimStr(V);
SetString(Result, V.ptr, V.len);
end else
Result := '';
end;function GetNewXMLNode(Data: PXMLData): PXMLNode;
var
nodes: PXMLDataArray;
begin
if Data.BufCount <= 0 then
begin
Nodes := AllocMem(SizeOf(TXMLDataArray));
Nodes.Next := Data.NodeBuffers;
Data.NodeBuffers := Nodes;
Data.IdleNodeBuffers := @Nodes.Nodes[0];
Data.BufCount := MAXBUF_NODES;
end;
Result := Data.IdleNodeBuffers;
FillChar(Result^, SizeOf(TXMLNode), 0);
Inc(Data.IdleNodeBuffers);
Dec(Data.BufCount);
end;procedure InitXMLData(const AXMLDataString: string; var Data: TXMLData; CountOfNodeBuffers: Integer);
begin
Data.Root := nil;
Data.XMLData.len := Length(AXMLDataString);
Data.XMLData.ptr := AllocMem(Data.XMLData.len);
Move(AXMLDataString[1], Data.XMLData.ptr^, Data.XMLData.len);
Data.BufCount := 0;
Data.IdleNodeBuffers := nil;
Data.NodeBuffers := nil;
end;procedure FreeXMLData(var Data: TXMLData);
var
Next, Nodes: PXMLDataArray;
begin
FreeMem(Data.XMLData.ptr);
Nodes := Data.NodeBuffers;
while Nodes <> nil do
begin
Next := Nodes.next;
FreeMem(Nodes);
Nodes := Next;
end;
FillChar(Data, SizeOf(Data), 0);
end;procedure ParseXMLData(AData: PXMLData);
const
NULLXMLStr: TXMLStr = (ptr: nil; len: 0); function GetElementName(var P: PChar; var IsEndElement: Boolean): TXMLStr;
var
S: PChar;
begin
Result := NULLXMLStr;
while not (P^ in ['<', #0]) do Inc(P);
if P^ = '<' then Inc(P);
IsEndElement := P^ = '/';
{if IsEndElement then
begin
Inc(P);
while not (P^ in ['>', #0]) do Inc(P);
Inc(P);
Result := GetElementName(P, IsEndElement);
Exit;
end; }
if P^ = '/' then Inc(P);
if P^ = #0 then Exit;
S := P;
while not (P^ in ['>', #0]) do Inc(P);
Result.ptr := S;
Result.len := P - S;
if P^ = '>' then Inc(P);
end; procedure OffsetElementEnd(var P: PChar);
begin
while not (P^ in ['<', #0]) do Inc(P);
if P^ = '<' then Inc(P);
if P^ = '/' then Inc(P);
if P^ = #0 then Exit;
while not (P^ in ['>', #0]) do Inc(P);
if P^ = '>' then Inc(P);
end; function GetNextElemntName(P: PChar): TXMLStr;
var
S: PChar;
begin
Result := NULLXMLStr;
while not (P^ in ['<', #0]) do Inc(P);
if P^ = '<' then Inc(P);
if P^ = '/' then Inc(P);
if P^ = #0 then Exit;
S := P;
while not (P^ in ['>', #0]) do Inc(P);
Result.ptr := S;
Result.len := P - S;
end; function GetContent(P: PChar): TXMLStr;
const
IgnoreChar = [#13, #10, #9, '&', '"', #0];
var
S: PChar;
begin
while P^ in ['"', #0] do Inc(P);
S := P;
while not (P^ in ['<', #0]) do Inc(P);
while P^ in IgnoreChar do Dec(P);
Result.ptr := S;
Result.len := P - S;
end;var
SrcPtr: PChar;
SrcLen: Integer; procedure GetXMLNode(AParent: PXMLNode; var ASrc: PChar);
var
NextName, NodeName: TXMLStr;
L: Integer;
Node: TXMLNode;
Child: PXMLNode;
IsEnd: Boolean;
begin
while ASrc - SrcPtr < SrcLen do
begin
FillChar(Node, SizeOf(Node), 0);
NodeName := GetElementName(ASrc, IsEnd);
if IsEnd then
begin
GetXMLNode(AParent.Parent, ASrc);
break;
end; if NodeName.len <= 0 then Continue; Child := GetNewXMLNode(AData);
Child^.Name := NodeName;
Child^.Parent := AParent;
if Assigned(AParent) then
begin
L := Length(AParent^.Child);
SetLength(AParent^.Child, L + 1);
AParent^.Child[L] := Child;
end;
NextName := GetNextElemntName(ASrc);
// ==> SameText
if (CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE,
NextName.ptr, NextName.len,
NodeName.ptr, NodeName.len) - 2) = 0 then
begin
Child^.Value := GetContent(ASrc);
OffsetElementEnd(ASrc);
end else
GetXMLNode(Child, ASrc)
end;
end;var
Src: PChar;
Len: Integer;
begin
Src := AData.XMLData.ptr;
Len := AData.XMLData.len;
SrcPtr := Src;
SrcLen := Len;
AData.Root := GetNewXMLNode(AData);
GetXMLNode(AData.Root, Src);
end;
procedure TForm1.Button1Click(Sender: TObject); procedure DisplayNodes(Node: PXMLNode);
var
I, L: Integer;
begin
if not Assigned(Node) then Exit;
Memo1.Lines.Add(Format('%s%s = %s', ['', GetString(Node.Name), GetString(Node.Value)]));
L := Length(Node.Child);
for I := 0 to L - 1 do
DisplayNodes(Node.Child[i]);
end;var
XMLData: TXMLData;
List: TStringList;
Start: Cardinal;
begin
LIst := TStringList.Create;
List.LoadFromFile('2.txt'); Start := GetTickCount;
InitXMLData(List.Text, XMLData, 100);
ParseXMLData(@XMLData);
Caption := InttoStr(GetTickCount - Start); DisplayNodes(XMLData.Root);
FreeXMLData(XMLData);
end;
在这里特别感谢errorc0de()现在还是不清楚为什么用XMLDocument解析的速度会那么慢。难道在内存访问树结构的数据非常耗时间吗?XMLDocument到底是如何在解析xml文件?