我需要建议在Delphi中使用什么(我使用Delphi 2009)来尽可能快地处理非常大的XML文件(例如100 MB).
我需要输入XML,从我的程序中访问和更新其中的数据,然后再次导出修改后的XML.
希望输入和输出可以在快速的Windows机器上在几秒钟内完成.
澄清.我希望我需要使用DOM,因为访问数据结构以开发报告和更新数据非常重要,我需要这个功能非常快.
输入仅对文件加载执行一次,输出仅对文件保存完成,通常在退出时只执行一次.这些也应该很快,但不如内存中数据访问和更新那么重要.
我的理解是第三方解析器只能帮助输入和输出,而不是一旦加载到内存中就使用和修改数据.或者我错了?
我已经尽了最大努力,无法弄清楚这里发生了什么.它在Delphi 4中运行良好.在升级到Delphi 2009之后,我不知道这是否应该是它应该工作的方式,或者它是否是一个问题:
这是我的程序菜单在Delphi 2009下的设计模式中的样子:
请注意,主菜单和文件子菜单中的每个单词都有一个带下划线的字母.应该是这样的.这个带下划线的字母称为加速键,是Windows应用程序的标准字母,因此您可以使用Alt键和该字母快速选择菜单项,然后使用键盘而不是鼠标快速选择子菜单项.
通过使用"&"字符作为项目标题的一部分,您可以通过这种方式获得它们,例如:Save&As ...
当我运行我的应用程序,并使用鼠标打开文件菜单时,它看起来像这样:
主菜单中的字符带下划线,但"文件"菜单中没有下划线.
相反,我使用Alt-F键打开文件子菜单,然后看起来像这样:
并且所有Accelerator Key字母都有正确的下划线.
我玩过AutoHotKeys选项,但这不是问题.
以前有人遇到过这个问题吗?第二个图像中的示例是否是我不知道的正确行为?或者我可能错过了一些选项或编码错误?
2009年11月(一年后):mghie似乎已经找到了根源,并找出了问题所在.请参阅下面接受的答案.
使用Screen.DesktopHeight和Screen.DesktopWidth,我可以获得"虚拟"桌面的大小,我相信它适用于一个或多个显示器.
我将应用程序的位置(顶部和左侧)和大小(高度和宽度)保存到注册表中.当它打开时,我想确保它完全可见,因为它可能已部分移动到可见区域之外,或者屏幕尺寸可能已经改变,例如通过屏幕设置或移除监视器.
我基本上可以用这段代码来做:
if MyForm.Width > screen.DesktopWidth then
MyForm.Width := screen.DesktopWidth;
if MyForm.Height > screen.DesktopHeight then
MyForm.Height := screen.DesktopHeight;
if (MyForm.Left + MyForm.Width) > screen.DesktopWidth then
MyForm.Left := screen.DesktopWidth - MyForm.Width;
if MyForm.Left < 0 then MyForm.Left := 0;
if (MyForm.Top + LogoAppForm.Height) > screen.DesktopHeight then
MyForm.Top := screen.DesktopHeight - LogoAppForm.Height;
if MyForm.Top < 0 then MyFormTop := 0;
Run Code Online (Sandbox Code Playgroud)
这没关系,除了它没有考虑通常(但不总是)在桌面底部的任务栏.因此,如果任务栏妨碍了我的应用程序窗口,我的应用程序就会变得模糊不清.
如何获取排除任务栏位置的屏幕的可用位置和大小设置?
Windows 7在其控制面板,外观和个性化,显示设置上添加了将文本和其他项目放大125%或150%的功能.
完成后,我的Delphi 2009程序的表单和对话框的一些内容被切断.
我需要做些哪些更改才能确保在Windows 7上的任何放大设置下,我的所有表单和对话框都能正常显示.
这是Delphi 2009,因此Unicode适用.
我有一些代码将缓冲区中的字符串加载到StringList中,如下所示:
var Buffer: TBytes; RecStart, RecEnd: PChar; S: string;
FileStream.Read(Buffer[0], Size);
repeat
... find next record RecStart and RecEnd that point into the buffer;
SetString(S, RecStart, RecEnd - RecStart);
MyStringList.Add(S);
until end of buffer
Run Code Online (Sandbox Code Playgroud)
但是在一些修改过程中,我改变了逻辑,以便最终添加相同的记录,但是作为单独派生的字符串而不是通过SetString,即
var SRecord: string;
repeat
SRecord := '';
repeat
SRecord := SRecord + ... processed line from the buffer;
until end of record in the buffer
MyStringList.Add(SRecord);
until end of buffer
Run Code Online (Sandbox Code Playgroud)
我注意到的是StringList的内存使用从52 MB上升到大约70 MB.这增加了30%以上.
为了回到我的较低的内存使用量,我发现我必须使用SetString来创建字符串变量以添加到我的StringList,如下所示:
repeat
SRecord := '';
repeat
SRecord := SRecord + …Run Code Online (Sandbox Code Playgroud) 我目前在我的程序中自动检测文本中的超链接.我做的很简单,只查找http://或www.
但是,用户建议我将其扩展为其他形式,例如:https://或.com
然后我意识到它可能不止于此,因为有ftp和mailto和文件,所有其他顶级域名,甚至电子邮件地址和文件路径.
我认为最好的方法是通过遵循当前使用的一些常用的标准超链接检测规则集来限制它.也许Microsoft Word是如何做到的,或者RichEdit是如何做到的,或者你知道更好的标准.
所以我的问题是:
是否有内置函数,我可以从Delphi调用来进行检测,如果有,那么调用会是什么样的?(我计划将来去FireMonkey,所以我更喜欢能在Windows之外运行的东西.)
如果没有可用的功能,是否有一些地方我可以找到一组记录在Word,RichEdit中检测到的内容的规则,或者应该检测到的任何其他规则集?那将允许我自己编写检测代码.
是否有Delphi的解析器代码或解析器组件或将接受BNF(Backus-Naur Form)表示法作为输入并生成Delphi(或pascal)代码进行解析的程序?
这样做的原因是我将尝试在GEDCOM标准的各种版本(用于家谱)之后完美地解析数据集,并且需要在达到令牌时处理从一个州到另一个州的文件.我更喜欢一个自动程序来完成设置基本pascal代码的粗略工作,为我做状态处理.
否则,我将不得不自己手动构建状态结构.
我确实看到了以下问题(并且TinyPG看起来很好,但我需要Delphi代码): 解析器生成器,在给定BNF语法的情况下输出C#?
如果没有这样的野兽,是否还有其他工具可以使这项任务更容易?
通过关于分析工具的所有问题,我很惊讶地发现了我之前从未听说过的VTune.700美元,比AQTime贵.
但是在我决定放弃AQTime的大笔资金之前,有没有人使用VTune用于Delphi,如果有的话,你认为它有什么好处可能使它成为比AQTime和Delphi的其他分析工具更好的选择在那里?
我有一小部分关键字.我真正想做的是类似于:
case MyKeyword of
'CHIL': (code for CHIL);
'HUSB': (code for HUSB);
'WIFE': (code for WIFE);
'SEX': (code for SEX);
else (code for everything else);
end;
Run Code Online (Sandbox Code Playgroud)
不幸的是,CASE语句不能像字符串一样使用.
我可以使用直接的IF THEN ELSE IF结构,例如:
if MyKeyword = 'CHIL' then (code for CHIL)
else if MyKeyword = 'HUSB' then (code for HUSB)
else if MyKeyword = 'WIFE' then (code for WIFE)
else if MyKeyword = 'SEX' then (code for SEX)
else (code for everything else);
Run Code Online (Sandbox Code Playgroud)
但我听说这是相对低效的.
我一直在做的是:
P := pos(' ' + MyKeyword + …Run Code Online (Sandbox Code Playgroud) 我的程序中有一个"查找文件"功能,可以找到我的程序读取的带有.ged后缀的文本文件.我在类似于资源管理器的窗口中显示找到的结果,如下所示:

我使用标准的FindFirst/FindNext方法,这非常有效.上面显示的584个文件可在几秒钟内找到并显示.
我现在要做的是在显示屏上添加两列,显示每个文件中包含的"Source"和"Version".此信息通常位于每个文件的前10行内,如下所示:
1 SOUR FTM
2 VERS Family Tree Maker (20.0.0.368)
Run Code Online (Sandbox Code Playgroud)
现在我自己解析这个问题没有问题,这不是我要问的问题.
我需要帮助的只是如何最快速地从这些文件加载前10行,以便我可以解析它们.
我试图做一个StringList.LoadFromFile,但加载大文件需要花费太多时间,例如1 MB以上的文件.
由于我只需要前10行左右,我最好如何获得它们?
我正在使用Delphi 2009,我的输入文件可能是也可能不是Unicode,所以这需要适用于任何编码.
跟进:谢谢Antonio,
我最终做了这个工作正常:
var
CurFileStream: TStream;
Buffer: TBytes;
Value: string;
Encoding: TEncoding;
try
CurFileStream := TFileStream.Create(folder + FileName, fmOpenRead);
SetLength(Buffer, 256);
CurFileStream.Read(Buffer[0], 256);
TEncoding.GetBufferEncoding(Buffer, Encoding);
Value := Encoding.GetString(Buffer);
...
(parse through Value to get what I want)
...
finally
CurFileStream.Free;
end;
Run Code Online (Sandbox Code Playgroud) delphi ×10
delphi-2009 ×2
large-files ×2
appearance ×1
aqtime ×1
bnf ×1
file-io ×1
gedcom ×1
hyperlink ×1
intel-vtune ×1
lookup ×1
menu ×1
optimization ×1
parsing ×1
pchar ×1
position ×1
profiling ×1
screen ×1
setstring ×1
size ×1
string ×1
taskbar ×1
unicode ×1
windows-7 ×1
xml ×1