使用PHP,我试图从Pervasive DB v9.5读取数据并将其插入到Windows 2008上的PostgreSQL 9.3(编码:UTF-8)。我没有选择或编写PervasiveDB(我只是从中读取数据) )。使用ODBC,我从Pervasive读取数据并将其写入控制台,没有任何问题。但是,当我尝试将其插入Postgre时遇到
Warning: pg_execute(): Query failed: ERROR: invalid byte sequence for encoding "UTF8": 0x94 in file.php on line ..
所以,我看到Postgres不喜欢我给的字符串。
然后我用
var_dump(iconv_get_encoding('all'));
并看到我的编码是ISO-8859-1
并使用
修改字符串iconv ( 'ISO-8859-1' , 'UTF-8' , $a)
现在,错误消失了。然而,到达Postgres的字符串不正确。
我使用的代码如下。我的测试字符串是aöaçaşaıağaüaÖaÇaŞaİaĞaÜ
$ a是来自Pervasive的字符串
echo $a;
给aöaçaşaıağaüaÖaÇaŞaİaĞaÜ
echo iconv ( 'ISO-8859-1' , 'UTF-8' , $a)
给a┬öa┬ça┬şa┬ıa┬ğa┬üa┬Öa┬Ça┬Şa┬İa┬Ğa┬Ü
<?php
//var_dump(iconv_get_encoding('all'));
$conn = pg_connect("host=localhost port=5432 dbname=xxx user=xxx password=".$argv[1]);
$result = pg_prepare($conn, "my_query", 'SELECT * FROM func_my_deneme($1)');
$connect_string = "DRIVER={Pervasive ODBC Client Interface}; SERVERNAME=localhost; SERVERDSN=xxx;";
$pervasiveconn = odbc_connect($connect_string, 'xxx', 'xxx');
$pervasive_result = odbc_exec($pervasiveconn ,"SELECT something");
while(odbc_fetch_row($pervasive_result)){
$a=odbc_result($pervasive_result,1);
echo $a;
$result = pg_execute($conn, "my_query", array(iconv ( 'ISO-8859-1' , 'UTF-8' , $a)));
}
?>
答案 0 :(得分:3)
你似乎只是在看这两个编码交换中的一个。
你有:
(pervasive's native encoding) -> (PHP string)
和
(PHP string) -> (PostgreSQL)
其中,您只是明确处理第二个问题。您假设Pervasive的ODBC驱动程序返回的数据是PHP的默认编码,在您的系统上是iso-8859-1。
您的测试表明假设可能是正确的,但简单地回显字符串并不是一个好的方法,因为这引入了另一个编码步骤:
(PHP string) -> (whatever decodes it for viewing)
是一个网络浏览器,终端或其他什么。如果观众希望某些编码与Pervasive使用的编码相同,则会对输出进行核心解码。
尝试:
echo $a;
echo "aöaçaşaıağaüaÖaÇaŞaİaĞaÜ";
并确保查看器显示两者的相同值。确保编辑源文件的编码设置为iso-8859-1
,而不是其他编码,以便粘贴的字符串的字面字节正确。
此时如果您的编辑器设置正确,您应该会收到错误,因为并非所有这些字符在iso-8859-1中都是合法的。第一个无效的是ş
。
很明显,来自Pervasive的东西不能是iso-8859-1。要真正打印latin-1字符串,您可以回显转义的字节。例如,这个字符串:
aöaçaaaüaÖaÇaaaaÜ
其中所有字符都是合法的iso-8859-1,以iso-8859-1编码打印:
echo "a\xf6a\xe7aaa\xfca\xd6a\xc7aaaa\xdc"
这里,十六进制转义用于指定非7位字符,以明确确保字节序列的编码符合您的想法,而不会对文本编辑器等造成任何混淆。
Betcha在您查看时无法正确打印,因为无论读取什么输入都不能将其解码为iso-8859-1。
你应该做的是查看从Pervasive获得的字符串的 bytes ,看看它到底是什么。然后确定其编码并将其解码为utf-8,然后您可以通过client_encoding = utf-8
连接将其发送到PostgreSQL。 @deceze为此建议bin2hex
(我不会说PHP,所以不知道该建议什么)。所以显示输出:
echo bin2hex($a) . "\n";
或 - 甚至更好 - 确保从配置/文档中确定来自Pervasive的数据的编码是什么,而不是猜测。或者强迫它。
快速浏览一下Pervasive文档,显示ODBC驱动程序有一个encoding
参数,该参数获取所需编码的代码页ID。所以试试:
$connect_string = "DRIVER={Pervasive ODBC Client Interface}; SERVERNAME=localhost; SERVERDSN=xxx; encoding=65001";
(微软至少将65001定义为每this doc个utf-8的代码页。)