String 如何在Delphi Xe2中使用新类型的字符串?
请注意,sarnold对问题进行了大量编辑;原著 整个问题作为评论保留在问题中。如果我 有些不清楚的地方,也许原始帖子会有所帮助。)我要走了 它只是一个注释,所以未来的编辑不需要总是参考 问题(编辑历史记录。) 我正在使用Delphi Xe2,需要了解如何使用ANSI的帮助 字符串、Unicode字符串和宽字符串, 尤其是在编写用于其他语言(如 如VB、C++、C语言) 我需要使用DelphiXe2编写一个DLL来执行简单的字符串操作 在Unicode字符串上。此DLL需要与一个isString 如何在Delphi Xe2中使用新类型的字符串?,string,delphi,dll,String,Delphi,Dll,请注意,sarnold对问题进行了大量编辑;原著 整个问题作为评论保留在问题中。如果我 有些不清楚的地方,也许原始帖子会有所帮助。)我要走了 它只是一个注释,所以未来的编辑不需要总是参考 问题(编辑历史记录。) 我正在使用Delphi Xe2,需要了解如何使用ANSI的帮助 字符串、Unicode字符串和宽字符串, 尤其是在编写用于其他语言(如 如VB、C++、C语言) 我需要使用DelphiXe2编写一个DLL来执行简单的字符串操作 在Unicode字符串上。此DLL需要与一个isSimple
SimpleShareMem
或
ShareMem
或不带内存管理器。此DLL需要可从外部调用
语言如VB、C++、C<./P>
默认情况下,字符串现在应该是Unicode字符串。我们应该使用
Embarcadero要用这些弦吗
字符串可以是:(a)不支持Unicode的单字节字符
或(b)宽字符串,其中每个字符需要两个字节。(这些是
支持Unicode,但它们不是UTF-8字符串。)
有两种指针类型可用:PAnsiChar
和PWideChar
(有
没有可用的指针)PChar
是的别名
PWideChar
——这是否意味着我们总是需要分配2*长度
这些字符串的内存量?(同样,我们是否需要分裂
通过2
读取内存以获取这些字符串的长度?)
对于字符串常量,是否需要在
源代码?例如:
Const MyCo = 'test';
或
当我们在字符串变量之间执行赋值时呢
s := st;
如果重新编写:
s := WideString(st);
我们应该在字符串中包含Unicode字节顺序标记吗?应该怎么做
我们在字符串中包含BOM
我们应该如何在不同的Windows代码页中使用ANSI字符串?如果
我们收到一个带有代码页1200的ANSI字符串,我们是否应该重新编码该字符串
还是按原样使用它
我们应该如何使用TEncoding
类在Unicode、UTF-8、,
WideString和AnsiString类
使用宽字符串或Unicode是否会造成严重的性能损失
弦
我们是否应该编写只需要使用WideString的接口
使用通用内存管理器时的变体
我们是否应该为PChar
编写需要长度参数的接口,
PAnsiChar
和PWideChar
参数类型
如何编写接口来确定文件是否以Unicode存储,
UTF-8、ANSI或宽字符?我们应该如何确定要使用的格式
将文件写回时使用
我们应该只使用程序吗?或者函数也可以工作吗
谢谢,新年快乐。我得到的印象是Gu正在从Delphi 7升级到支持Unicode的版本(D2009+),并且正在寻求有关如何处理新字符串的建议
卡里·詹森(Cary Jensen)的白皮书解决了问题中提出的大部分(如果不是全部的话)问题
我通常会把这个放在评论中,但是评论列表已经很长了,我觉得这个链接(可能会帮助更多的人而不仅仅是顾)更容易在答案中找到。因为,你最好把这些问题放在rsdn.ru论坛,我觉得它们对新手比大师更开放
Gu,基本上,您应该阅读Delphi XE2中的手册。一切都在那里,只要用心去读就行了
1) 您根本不应该创建DLL。你应该做BPL。
DLL旨在与普通C接口(如Win32 API)协作。
这些是最原始的类型,没有任何副作用。
C因其原始性被称为“独立于机器”的汇编程序,DLL接口就是其中的一种
DLL可能用于与其他语言兼容,因为它们使用了与Delphi不兼容的另一种副作用。然后DLL强制执行最原始的合作,并从接口中消除所有副作用。通过将内部通信级别降低到最简单的类型,DLL接口加强了兼容性
但是当您需要将Delphi与Delphi交互时,最好允许Delphi关心所有兼容性问题。这就是BPL在Delphi3中的用途。
没有理由为此使用DLL
当然,如果你愿意的话,你可以开枪打自己的脚。
2) 您不应该在XE2中使用WideString,而应该使用UnicodeString。
字符串手册特别强调了这一点。看来你们只是并没有读手册
3) 字符串常量是Unicode格式的。(但字符常量在ANSI或Unicode中是随机的,这会导致意外的行为错误)。
而且不需要询问和相信任何人的话——只需在任何查看器中打开exe并搜索这些常量,就可以在2字节UCS-2(又名WideChar)编码中找到它们
4) Unicode BOM用于确定CPU字节顺序,是Intel还是Motorola时尚。
当您为Windows开发时,您只能使用Intel字节顺序,因此不需要BOM表
5) 你写的关于长度和内存大小的整段话都很含糊。你所说的长度是什么意思,它是用什么单位来测量的,从哪里来的
我假设长度指的是不包括任何“幕后”服务结构/字符的字符数。这就是内置函数System.Length(字符串或数组)返回的值。
然而,如果这个假设是错误的,那么下面的答案也是错误的
你是否应该乘以2的问题只是一个坏代码的标志。
你应该总是乘一些东西,几年前你已经应该乘了。
乘以。。。什么?按SizeOf(使用字符变量)或SizeOf(使用字符类型)。
然后t将是Delphi,它将自动确定需要多少内存。
和Deal
s := WideString(st);
function CDF_File_Buffer.GetStringNoBounds(const ofs, len: integer): string;
// Распознать кодировку, не проверять адреса
var cntDOS, cntWin, cntWeird, i : Cardinal;
sBuf: RawByteString; cp: word;
ptr, ptr_i: PAnsiChar;
const rusDOS: set of AnsiChar = [#$80..#$AF, #$E0..#$F1];
rusWin: set of AnsiChar = [#$C0..#$FF];
begin
ptr := Pointer(Header); Inc(ptr, ofs);
case textCharset of
tcsGuess:
begin
ptr_i := ptr; cntDOS :=0; cntWin :=0; cntWeird:=0;
for i := 1 to len do begin
if ptr_i^ in rusDOS then Inc(cntDOS);
if ptr_i^ in rusWin then Inc(cntWin);
if (ptr_i^ < #32) or ((ptr_i^ >= #127) and not(ptr_i^ in rusWin) and not(ptr_i^ in rusDOS))
then inc(cntWeird);
Inc(ptr_i);
end;
if (cntWin > cntDOS) or (cntWeird > cntDOS) then cp := 1251 else cp := 866;
end;
tcsWin: cp := 1251;
tcsDOS: cp := 866;
else cp := 0; // быть не должно такого
end;
SetString(sBuf,ptr,len);
for i := 1 to Length(sBuf) do if sBuf[i] = #0 then sBuf[i] := #7;
// Не совсем корректно заменять нули, но
// 1) неизвестно, что вообще в этом поле может быть
// 2) файлы создаются в программе на C++, где нулей в строках не может быть
// 3) семантику надо выводить на экран, а Windows написана на C++
SetCodePage(sBuf, cp, false);
Result := string(sBuf);
end;
function CDF_File_Buffer.GetString(const ofs, len: integer; const min, max: integer): string;
begin
if (ofs <= 0) or (len <= 0) then
Exit( '--- нет текста ---');
if Cardinal(ofs + (len-1)) >= TotalSize then //меньше нуля уже не будет, убираем Warning
Exit('--- За пределами файла ---');
Result := '--- За пределами допустимой области: слишком близко к ';
if ofs < min then Exit(Result + 'началу ---');
if ofs + (len-1) > max then Exit(Result + 'концу ---');
Result := GetStringNoBounds(ofs, len);
end;
function CDF_File_Buffer.GetString(const ofs, len: integer): string;
begin
Result := GetString(ofs, len, 0, TotalSize-1);
end;