最近我被一位声誉卓着的SO用户告知,它TStringList有分裂错误,导致它无法解析CSV数据.我没有被告知这些错误的性质,在互联网上搜索包括Quality Central没有产生任何结果,所以我问.什么是TStringList拆分错误?
请注意,我对没有根据意见的答案感兴趣.
我知道的:
并不多......其中一个就是,这些错误很少出现在测试数据中,但在现实世界中却很少见.
另一方面,如上所述,它们阻止了对CSV的正确解析.认为很难用测试数据重现错误,我(可能)寻求帮助,他们尝试在生产代码中使用字符串列表作为CSV解析器.
无关紧要的问题:
我获取了有关'Delphi-XE'标记问题的信息,因此由于"空格字符被视为分隔符" 功能而无法解析,因此不适用.因为StrictDelimiterDelphi 2006 引入的属性解决了这个问题.我,我自己,正在使用Delphi 2007.
此外,由于字符串列表只能包含字符串,因此它只负责拆分字段.涉及由区域差异等引起的字段值(fi日期,浮点数......)的任何转换难度都不在范围内.
基本规则:
CSV没有标准规范.但是从各种规范中可以推断出基本规则.
下面演示TStringList如何处理这些.规则和示例字符串来自维基百科.括号([ ])叠加在字符串周围,以便能够通过测试代码查看前导或尾随空格(相关).
空间被认为是一个领域的一部分,不应该被忽视.
Test string: [1997, Ford , E350] Items: [1997] [ Ford ] [ E350]
带嵌入逗号的字段必须包含在双引号字符中.
Test string: [1997,Ford,E350,"Super, luxurious truck"] Items: [1997] [Ford] [E350] [Super, luxurious truck]
具有嵌入式双引号字符的字段必须包含在双引号字符中,并且每个嵌入的双引号字符必须由一对双引号字符表示.
Test string: [1997,Ford,E350,"Super, ""luxurious"" truck"] Items: [1997] [Ford] [E350] [Super, "luxurious" truck]
嵌入换行符的字段必须包含在双引号字符中.
Test string: [1997,Ford,E350,"Go get one …
我想使用Delphi的2009 TGridPanel,但我不明白如何正确使用它.
例如,我希望有一个包含4列的GridPanel,它应该具有GripPanels宽度的25%.
所以我在表单上放了一个GripPanel并添加了4个ColumnItems.我给列项目SizeStyle ssPercent,现在我尝试给每个ColummItem一个值25(对象检查器).但由于某些原因,对象检查员不接受值25.它会自动更改为'23,8095238095238'.有人可以解释一下如何使用这些组件吗?谢谢!
如.关闭相关问题 - 下面添加更多示例.
下面的简单代码(找到顶级Ie窗口并枚举其子代)与'32位Windows'目标平台一起正常工作.早期版本的Delphi也没有问题:
procedure TForm1.Button1Click(Sender: TObject);
function EnumChildren(hwnd: HWND; lParam: LPARAM): BOOL; stdcall;
const
Server = 'Internet Explorer_Server';
var
ClassName: array[0..24] of Char;
begin
Assert(IsWindow(hwnd)); // <- Assertion fails with 64-bit
GetClassName(hwnd, ClassName, Length(ClassName));
Result := ClassName <> Server;
if not Result then
PUINT_PTR(lParam)^ := hwnd;
end;
var
Wnd, WndChild: HWND;
begin
Wnd := FindWindow('IEFrame', nil); // top level IE
if Wnd <> 0 then begin
WndChild := 0;
EnumChildWindows(Wnd, @EnumChildren, UINT_PTR(@WndChild));
if WndChild <> 0 then
..
end; …Run Code Online (Sandbox Code Playgroud) 嗨,我想检索硬盘唯一(硬件)序列号.我使用了一些功能,但在Windows 7或Vista中,由于管理员权限,它们无法正常工作.是否可以在不以管理员身份运行时检索它?
众所周知,当我们调用类的构造函数时:
instance := TSomeClass.Create;
Run Code Online (Sandbox Code Playgroud)
Delphi编译器实际上做了以下事情:
它简单易懂.但我不太确定编译器如何处理第二步和第三步中的异常.
似乎没有明确的方法在D2010中使用RTTI构造函数方法创建实例.所以我在Spring Framework for Delphi中编写了一个简单的函数来重现创建过程.
class function TActivator.CreateInstance(instanceType: TRttiInstanceType;
constructorMethod: TRttiMethod; const arguments: array of TValue): TObject;
var
classType: TClass;
begin
TArgument.CheckNotNull(instanceType, 'instanceType');
TArgument.CheckNotNull(constructorMethod, 'constructorMethod');
classType := instanceType.MetaclassType;
Result := classType.NewInstance;
try
constructorMethod.Invoke(Result, arguments);
except
on Exception do
begin
if Result is TInterfacedObject then
begin
Dec(TInterfacedObjectHack(Result).FRefCount);
end;
Result.Free;
raise;
end;
end;
try
Result.AfterConstruction;
except
on Exception do
begin
Result.Free;
raise;
end;
end;
end;
Run Code Online (Sandbox Code Playgroud)
我觉得这可能不是100%正确.所以请告诉我方式.谢谢!
在下面的测试程序中,每个测试线程TThreadList在开始执行时将其句柄添加到全局,并在其执行即将结束时从同一列表中删除其句柄.
另外,为了测试目的,每个线程确保在主线程锁定列表之前添加其句柄(复制它们的句柄并开始等待它们完成).线程还确保在主线程锁定列表之前不删除它们的句柄.
测试程序运行良好,最多可达50-60个线程.之后,WaitForMultipleObjects调用开始失败WAIT_FAILED,GetLastError返回87(ERROR_INVALID_PARAMETER).目前它启动了100个线程.我的问题是,我做错了什么?
该程序使用XE2编译 - 更新4,32位目标平台.测试盒是W7x64.
program Project1;
{$APPTYPE CONSOLE}
{$R *.res}
uses
windows,
sysutils,
classes,
syncobjs;
type
TTestThread = class(TThread)
private
FAckStarted: TEvent;
function GetAckHandle: THandle;
class var
ThreadList: TThreadList;
WaitEnd: THandle;
protected
procedure Execute; override;
public
constructor Create;
destructor Destroy; override;
property AckHandle: THandle read GetAckHandle;
end;
{.$DEFINE FREEONTERMINATE}
constructor TTestThread.Create;
begin
inherited Create(True);
FAckStarted := TEvent.Create;
{$IFDEF FREEONTERMINATE}
FreeOnTerminate := True;
{$ENDIF}
end;
destructor TTestThread.Destroy;
begin
FAckStarted.Free; …Run Code Online (Sandbox Code Playgroud) 我有一个DLL,其中我有一个返回pchar的函数.(为了避免使用borlndmm)我最初做的是将字符串作为pchar转换并返回
Result := pChar(SomeFuncThatReturnsString)
Run Code Online (Sandbox Code Playgroud)
但是我90%的时间都得到了预期的结果,而其他时候我什么都没回来.
然后我开始认为我需要为pchar分配内存,并且我原来的方式就是拥有一个pchar指向内存,这并不总是在最初调用该函数时的内容.所以我现在有这个
Result := StrAlloc(128);
Strcopy(Result,PAnsiChar(Hash(Hash(Code,1,128),2,128)));
Run Code Online (Sandbox Code Playgroud)
但这让我不得不清理程序端的已分配内存
StrDispose(Pstr);
Run Code Online (Sandbox Code Playgroud)
所以64美元的问题是:从DLL中的函数返回PChar时我是否必须分配内存,或者我可以将其转换为PChar?
我有一些" FreeOnTerminate"工作线程,它们在TThreadList开始执行时添加其句柄,并在执行结束时从中删除.他们还会检查一个全局事件对象,通知他们取消他们的工作.
以下是在主线程中运行的部件,它向事件发出信号并等待可能的工作线程结束.WorkerHandleList是全球性的ThreadList.
...
procedure WaitForWorkers;
var
ThreadHandleList: TList;
begin
ThreadHandleList := TWorkerThread.WorkerHandleList.LockList;
TWorkerThread.WorkerHandleList.UnlockList;
WaitForMultipleObjects(ThreadHandleList.Count,
PWOHandleArray(ThreadHandleList.List), True, INFINITE);
end;
initialization
TWorkerThread.RecallAllWorkers := TEvent.Create;
TWorkerThread.WorkerHandleList := TThreadList.Create;
finalization
TWorkerThread.RecallAllWorkers.SetEvent;
WaitForWorkers;
TWorkerThread.RecallAllWorkers.Free;
TWorkerThread.WorkerHandleList.Free;
Run Code Online (Sandbox Code Playgroud)
我认为,这种设计有一个缺陷,即我必须在等待线程的句柄之前解锁列表,因为这会导致死锁,因为线程本身会从同一列表中删除它们的句柄.没有任何锁定,上下文切换可能导致线程释放自己导致WaitForMultipleObjects立即返回WAIT_FAILED.我不能使用另一个锁,因为WaitForMultipleObjects阻塞,我将无法从主线程释放锁.
我可以通过多种方式修改此设计,包括不使用FreeOnTerminate线程,这将保证有效句柄,直到它们被明确释放.或者仅从主线程修改线程句柄列表.或者其他人......
但我想问的是,如果不改变设计,是否有解决这类问题的方法?例如,在从列表中删除其句柄之前,是否会在工作线程代码中睡眠,或者调用SwitchToThread导致所有非工作线程都运行?够跑吗?
我无法弄清楚如何更改默认的构建/编译设置.项目选项对话框左下角的小默认复选框消失了.该文件规定:
The Default checkbox that appeared at the lower edge of many Project Options pages has been removed from the product. If you want to specify options as the default for multiple projects, the suggested alternative is to use option sets instead.
关于" 选项集 "," 配置管理器 "等我会四处走动.这甚至可能吗?什么是"指定选项为默认多个项目"是什么意思?如果我有多个项目那么这意味着那些项目及其选项存在,我如何设置默认值为已设置的东西?新项目怎么样?
我的应用程序完成初始化并创建了主窗体后,我想要执行的功能.我确实在表单OnShow事件中有代码(称为ProcedureX),但我刚刚注意到它被调用了两次,因为OnShow正在触发两次.它在主程序DPR调用时触发:
Application.CreateForm(TMainForm, MainForm) ;
Run Code Online (Sandbox Code Playgroud)
正如我所料.但在那之后,当我从包含表格屏幕位置的INI文件中读取内容时,我有一个电话:
MainForm.position := poScreenCenter ;
Run Code Online (Sandbox Code Playgroud)
这样,它会再次触发OnShow事件.
我在哪里可以调用ProcedureX,必须只调用一次,并且需要在执行之前创建主表单?
delphi ×10
delphi-xe2 ×4
delphi-2007 ×2
32bit-64bit ×1
csv ×1
delegates ×1
delphi-2006 ×1
delphi-2010 ×1
delphi-7 ×1
dll ×1
events ×1
forms ×1
hardware ×1
nested ×1
pchar ×1
rtti ×1
show ×1
tgridpanel ×1
tstringlist ×1