ansiToUtf8不适用于从Delphi 7转换的Delphi XE项目?

ansiToUtf8不适用于从Delphi 7转换的Delphi XE项目?,delphi,utf-8,delphi-7,oracle9i,delphi-xe,Delphi,Utf 8,Delphi 7,Oracle9i,Delphi Xe,有一个带有CL8MSWIN1251代码页设置的Oracle9DB和带有一些编辑字段的DelphiXE 我需要将Delphi7中的项目转换为DelphiXE项目,以便使用并能够查看UTF8数据 所以我用DelphiXE打开了dpr文件,它自动转换为dproj。但当我尝试向db中插入一些数据时,我得到的是问题符号(“?”),而不是一些utf8字符。 我尝试使用ansitoUTF8(edit1.text)转换编辑数据(Tedit)。但它不起作用。 然后我在XE中启动了一个新项目,很快添加了一些编辑来检

有一个带有CL8MSWIN1251代码页设置的Oracle9DB和带有一些编辑字段的DelphiXE

我需要将Delphi7中的项目转换为DelphiXE项目,以便使用并能够查看UTF8数据

所以我用DelphiXE打开了dpr文件,它自动转换为dproj。但当我尝试向db中插入一些数据时,我得到的是问题符号(“?”),而不是一些utf8字符。 我尝试使用ansitoUTF8(edit1.text)转换编辑数据(Tedit)。但它不起作用。 然后我在XE中启动了一个新项目,很快添加了一些编辑来检查ansitoutf8函数,它运行良好,并将数据插入到同一个db和同一个表中

有一条规则:我不能在db中更改代码页设置

begin
  adoquery1.close;
  adoquery1.sql.text:='insert into table (data1,data2) values ('+#39+ansitoUTF8(edit1.text)+#39+','+#39+ansitoUTF8(edit2.text)+#39+')';
  adoquery1.execsql;
end;

有什么建议吗?

CL8MSWIN1251不是UTF-8代码页,它是Oracle对Windows 1251(西里尔文)代码页的实现。Delphi XE始终使用UTF-16。Oracle数据库和客户端能够执行字符集转换。您应该正确设置客户端/会话的NLS_LANG参数。如果不想更改客户端代码页,可以发出ALTER会话集NLS_LANGUAGE=。。。登录时,仅为该会话更改它。对于带有Oracle 9i数据库的XE Unicode应用程序,您可以在客户端使用AL16UTF16来告知客户端数据为UTF-16格式,并让Oracle执行其转换

PS:代码类似于

#39+ansitoUTF8(edit1.text)+#39+...

是引入SQL注入漏洞的最佳方式。您应该使用绑定变量,或者至少使用像QuotedStr/ansiquettedstr这样的函数,以确保字符串保持字符串状态,并且不会成为错误用户手中的SQL命令。

Delphi XE与
AnsiToUTF8()
函数之间存在向后兼容性中断,事实上,在它调用的
Utf8Encode()
函数中

在DelphiXE中,它返回一个
RawByteString
类型的字符串。因此,您必须将结果类型强制为
UTF8String
。像这样:
UTF8String(ansitoUTF8(…)

但我想这可能不是你的问题

在代码中:

adoquery1.sql.text:='insert into table (data1,data2) values ('+#39+ansitoUTF8(edit1.text)+#39+','+#39+ansitoUTF8(edit2.text)+#39+')';
sql.text
表达式是一个
UnicodeString
,因此您将在连接表达式中使用Delphi XE编译器进行显式转换

下面这行行行吗

adoquery1.sql.text:='insert into table (data1,data2) values ('+#39+edit1.text+#39+','+#39+edit2.text+#39+')';

它应该在XE下工作,并且应该由VCL从原始
UnicodeString

转换为UTF8。您是否知道sql.text是一个字符串,因此类似于D2009中的UnicodeString?无论您以前做了什么,当分配给sql.text时,它都将转换为unicode。您可以通过使用查询参数来解决这个问题(无论如何,我建议这样做),将数据类型设置为ftString。您不能更改数据库代码页,但表是否在您的控制下?检查nvarchar类型:@ldsandon,没有“UTF-8代码页”这样的东西.UTF8是Unicode文本的表示法,代码页用于ANSI字符串,以在ANSI字符集和现在称为Unicode子集的字符集之间创建映射。@Cosmin:仅在Windows代码页65001中是UTF-8…@Idsandon:您说:
“CL8MSWIN1251不是UTF-8代码页”
;它假设一些代码页是UTF-8,而
CL8MSWIN1251
不是。它假设有多个
UTF-8
代码页,而事实上UTF8是一个符号,而不是一个代码页。Windows使用代码页65001处理UTF8数据的事实没有什么区别:代码页65001和UT之间的
1:1
映射F8是Windows的诀窍。UTF-8是一种字符编码/字符集,因此是一个代码页。好吧,我的断言可能会被误读(当然不需要多个UTF-8代码页)。好吧,所以给UTF-8一个代码页号不仅是Windows的诀窍,而且UTF-8是一种符号或“转换”,而不是代码页。您应该编辑答案以消除任何可能的混淆。+1.我实际上会声明这样的类型
type Ansi1251=type AnsiString(1251)
,然后强制使用
Ansi1251(AnsiToUTF8(…)
;这将使用
1251
代码页将
AnsiToUTF8
的结果视为ANSI文本中的文本,因此以下所有到Unicode和回到
1251
的转换将保留字节值。不要这样做。让Oracle执行其转换。正确配置Oracle,无需来回转换每次您需要写入数据时,我都会对代码页进行编码。Oracle比Delphi更了解国家语言支持。@Idsandon,据我所知,数据库列已定义为使用代码页1251,这是无法更改的,但OP希望将国际字符放在其中;OP希望首先对国际字符进行编码文本为UTF8,将其推入DB列中,保持不变,并且(我假设)当从数据库中读取文本时,手动执行转换。由于AnsiToUtf8的结果用于字符串连接,原始字节会转换回Unicode,我猜转换会映射到一些Unicode代码点,而这些代码点在代码页1251中没有等价的代码点。[…][…]强制将AnsiToUTF8的结果解释为
Ansi1251
可以保证转换为Unicode会返回可以在Ansi1251代码页中表示的字符;由于Ansi1251到Unicode到Ansi1251的转换保证是无损的,Oracle将保留UTF8文本(不会用问号替换任何内容)。由于UTF8是保存的,因此可以随意将其转换回Unicode。它在Delphi级别执行的任何操作都将在客户端/数据库级别通过Oracle转换,具体取决于NLS设置。如果他试图对数据库进行黑客攻击,以另一种编码发送UTF-8数据,则只有当且仅当客户端和datatabase设置为sa时,该操作才会起作用在任何其他情况下,它都会产生奇怪的结果。在索引/查询数据时,它也会有奇怪的行为,除非是纯二进制排序规则