我写了很多代码(D2010,win XP),我认为这对于未来的国际化来说是非常稳固的,但不是。它全部使用unicodestring(string)数据类型,到目前为止,我刚刚把英文字符放入unicode字符串。
似乎我必须拥有一个非常严重的unicode错误。我跟德国朋友谈过,并尝试了一些德国的ß,(ß是’ss’,应该是S和T之后的字母表)和ö等(注意umlaut),我的排序算法都没有工作了。结果非常混乱。垃圾。
从那时起,我一直在阅读广泛,并学习了很多关于unicode整理的不愉快的事情。事情看起来很严峻,比以前预想的要严峻,我已经把这个弄得很厉害了。我希望我错过了一些东西,事实上并不像现在看起来那么严峻。我一直在琢磨着看着windows api调用(RtlCompareUnicodeString),没有成功(保护错误),我无法让它工作。 API调用的问题我学到的是,它们在各种较新的Windows平台上发生变化,并且随着delphi的跨平台也越来越快,随着linux,我的应用程序是客户端服务器,所以我需要关心这一点,但是,是(坏)我会感激任何进步,即胜利api具体。
是否使用win api函数RtlCompareUnicodeString来明显的解决方案?如果是这样,我应该再次尝试,但是我已经对unicode整理涉及到的所有问题感到吃惊,我不清楚我应该做什么来比较这些字符串。
我了解到IBM ICU c opensource项目,但是有一个delphi包装器,尽管是旧版本的ICU。这似乎是一个非常全面的解决方案,是平台独立的。当然,我无法看到为此创建一个delphi包装(或更新现有的),以获得unicode整理的一个很好的解决方案?
我会很高兴听到两个层面的建议:
A)一个Windows特定的非便携式解决方案,我会很高兴,目前,忘记了客户端服务器的后果!
B)一个更便携的解决方案可以免除unicode api功能的各种XP / vista / win7变体,因此使我在XE2 mac支持和未来的linux支持方面取得了很好的成绩,更不用说客户端服务器的并发症。
Btw我真的不想做’make-do’解决方案,在比较之前扫描字符串并替换某些棘手的字符等,我已经阅读了。我给了上面的德语例证,这只是一个例子,我想让它为所有(或至少大多数,远东,俄语)语言工作,我不想为特定语言或两个语言做出解决方法。我也不需要任何关于排序算法的建议,它们很好,它只是字符串比较位是错误的。
我希望我失踪/做一些愚蠢的事情,这一切都是头痛的。
谢谢。
编辑,鲁迪,这里是我如何调用RtlCompareUnicodeString。对不起,迟到我一直在这个可怕的时间。
program Project26 {$APPTYPE CONSOLE} uses SysUtils; var a,b:ansistring; k,l:string; x,y:widestring; r:integer; procedure RtlInitUnicodeString( DestinationString:pstring; SourceString:pwidechar) stdcall; external 'NTDLL'; function RtlCompareUnicodeString( String1:pstring; String2:pstring; CaseInSensitive:boolean ):integer stdcall; external 'NTDLL'; begin x:='wef'; y:='fsd'; RtlInitUnicodeString(@k,pwidechar(x)); RtlInitUnicodeString(@l,pwidechar(y)); r:=RtlCompareUnicodeString(@k,@l,false); writeln(r); readln; end.
我意识到这很可能是错的,我不习惯直接调用api的行为,这是我最好的猜测。
关于你的StringCompareEx api函数。这看起来真的很好,但仅在Vista上使用,我正在使用XP。 StringCompare是在XP,但这不是Unicode!
要概述,基本任务是比较两个字符串,并根据当前窗口区域设置中指定的字符排序顺序进行比较。
如果ansicomparetext应该做到这一点吗?这对我来说并不奏效,但是有些人说应该这样做,其他我看过的建议应该是这样的。
当在德语区域设置中使用AnsiCompareText时,这是31个测试字符串所得到的(空格分隔 – 没有字符串包含空格): –
>ßßßöööööööööööss ss ss ss ss ss a a a a a a a
Sssbßßssss SSSSßßßssßßSSßßßzßzßz zzz
编辑2。
我还是很想知道如果我应该期望AnsiCompareText使用locale信息工作,就像lkessler所说的那样,lkessler也已经发布了关于这些主题的信息,并且似乎已经通过了这一点。
不过,从Rudy的建议来看,我也一直在检查CompareStringW – 它与CompareString共享相同的文档,所以它不是非Unicode的,如前所述。
即使AnsiCompareText不工作,虽然我认为应该是,win32api函数CompareStringW应该确实有效。现在我已经定义了我的API函数,我可以调用它,我得到一个结果,没有错误…但我得到相同的结果,无论输入字符串!它每次返回1 – 这意味着少于。这是我的代码
var k,l:string; function CompareStringW( Locale:integer; dwCmpFlags:longword; lpString1:pstring; cchCount1:integer; lpString2:pstring; cchCount2:integer ):integer stdcall; external 'Kernel32.dll'; begin; k:='zzz'; l:='xxx'; writeln(length(k)); r:=comparestringw(LOCALE_USER_DEFAULT,@k,3,3); writeln(r); // result is 1=less than,2=equal,3=greater than readln; end;
我觉得我现在有了很多痛苦。很高兴知道AnsiCompareText,而且我在上面的CompareStringW api调用中做错了什么。谢谢。
编辑3
首先,我自己修改了比较字符串的API调用,当我应该做PString(mystring)时,我传递了@mystring。现在这一切都正常工作。
r:=comparestringw(LOCALE_USER_DEFAULT,pstring(k),-1,pstring(l),-1);
现在,我可以想象我的沮丧,当我仍然得到了一样的排序结果,因为我一开始就这样做
>ßßßßßßßßööööööööööss ss ss a a a a a a a a a a
Sssbßßssss SSSSßßßssßßSSßßßzßzßz zzz
当我意识到排序顺序是正确的时候,你也可能会想象我非常沮丧,不要提及同时的快乐,而且它在正确的位置正确地回到了!这使得生病的人说,但是从来没有任何问题,这一切都归功于我缺乏德国的知识。我觉得排序是错误的,因为你可以看到上面的字符串从S开始,然后他们从ß开始,然后再次回到ß等等。那么我不会说德语,但是我仍然可以清楚地看到他们没有被正确排序 – 我的德国朋友告诉我,ß来自S,之前,我错了!发生的是字符串函数(AnsiCompareText和winapi CompareTextW)都使用’ss’替代每个’ß’,并且每个’ö’都具有正常的’o’…所以如果我把这些结果和搜索结果并按照我所描述的替换
>屁股屁股屁股Asss no no o on oo oo ooo ooo op po ss ss ss ss ssss
sss Sssa Sssb ssss ssss SSSS ssssss ssssss SSssss ssz sszss z zzz
对我来说看起来很正确!而且它一直是。
我非常感谢所有的建议,非常抱歉浪费了你这样的时间。那些德国人的ß让我感到困惑,内置delphi功能或其他任何东西都没有错。它只是看起来像那里。在我的测试数据中,我错误地将它们与正常的’组合在一起,任何其他的信都不会产生这种无序排除的错觉!波澜不惊的ß使我看起来很傻! SSS!
Rudy和lkessler我们都特别有帮助,我们都不得不接受lkessler的答案是最正确的,对不起Rudy。
解决方法
并且使用AnsiCompareStr区分大小写,如果您希望您的排序特定于用户的区域设置,则使用AnsiCompareText不区分大小写。
有关这方面的更多信息,请参阅:How can I get TStringList to sort differently in Delphi。