String 如何在Delphi Xe2中使用新类型的字符串?

String 如何在Delphi Xe2中使用新类型的字符串?,string,delphi,dll,String,Delphi,Dll,请注意,sarnold对问题进行了大量编辑;原著 整个问题作为评论保留在问题中。如果我 有些不清楚的地方,也许原始帖子会有所帮助。)我要走了 它只是一个注释,所以未来的编辑不需要总是参考 问题(编辑历史记录。) 我正在使用Delphi Xe2,需要了解如何使用ANSI的帮助 字符串、Unicode字符串和宽字符串, 尤其是在编写用于其他语言(如 如VB、C++、C语言) 我需要使用DelphiXe2编写一个DLL来执行简单的字符串操作 在Unicode字符串上。此DLL需要与一个isSimple

请注意,sarnold对问题进行了大量编辑;原著 整个问题作为评论保留在问题中。如果我 有些不清楚的地方,也许原始帖子会有所帮助。)我要走了 它只是一个注释,所以未来的编辑不需要总是参考 问题(编辑历史记录。)

我正在使用Delphi Xe2,需要了解如何使用ANSI的帮助 字符串、Unicode字符串和宽字符串, 尤其是在编写用于其他语言(如 如VB、C++、C语言) 我需要使用DelphiXe2编写一个DLL来执行简单的字符串操作 在Unicode字符串上。此DLL需要与一个is
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;