使用php over odbc检索DB2值的字符集问题

时间:2017-05-23 13:21:07

标签: php db2 odbc

我正在尝试通过PHP和odbc从DB2中进行选择,然后将这些值保存在文件中。正在执行代码的操作系统是Debian。我的工作如下:

$query = "SELECT NAME FROM DATABASE_EXAMPLE.TABLE_EXAMPLE";
$result = odbc_prepare($server, $query);
$success = odbc_execute($result);
$linias = "";

if ($success) {
    while ($myRow = odbc_fetch_array($result)) {
        $linias .=format_word($myRow['NAME'], 30) . "\r\n";  
}

generate_file($linias);


function format_word($paraula, $longitut) {
    return str_pad(utf8_encode($paraula), $longitut, " ", STR_PAD_LEFT);
}

function generate_file($linias) {

    $nom_fitxer = date('YmdGis');
    file_put_contents($nom_fitxer . ".tmp", $linias);
    rename($nom_fitxer . '.tmp', $nom_fitxer . '.itf');

}

问题是某些检索到的值包含西班牙语字母和重音符号。举例来说,其中一个值是“ÁNGULO”。如果我在我的浏览器上var_dump代码我得到了一个好的单词,但是当它写入文件时,它会在它上面添加奇怪的字符(这就是为什么我认为charset存在问题)。我尝试了不同的解决方法,但它只是让它变得更糟。使用Notepad ++(启用了UTF8编码)打开的文件如下所示:

Notepad++ capture

PHP中是否有一个在charsets之间进行转换的函数?

修改

按照erg说明,我做了进一步的研究:

DB2数据库使用IBM284字符集,因为我发现执行下一个命令:

select table_schema, table_name, column_name, character_set_name from SYSIBM.COLUMNS

Firefox称该页面编码为Unicode。 如果我这样做:

var_dump(mb_detect_encoding($paraula));

结果我得到了布尔(假)。

我已经改变了我的功能,以形成希望iconv解决冲突的词:

function format_word($paraula, $longitut) {
    $paraula : mb_convert_encoding($paraula, 'UTF-8');
    $paraula= iconv("IBM284", "UTF-8", $paraula);
    return $paraula;
}

但事实并非如此。看起来像ODBC它正在做一些编纂不好,这就是混乱的数据。如何修改odbc以修改到正确的字符集?我在Linux上看到一些改变语言环境的东西,但如果我在PC上执行命令语言环境,我得到:

LC_NAME="es_ES.UTF-8"
LC_ADDRESS="es_ES.UTF-8"
...

1 个答案:

答案 0 :(得分:1)

我将尝试从评论中总结出答案:

首先请注意,PHP utf8_encode将从ISO-8859-1转换为utf-8。如果您的数据库/ ODBC驱动程序未返回ISO-8859-1编码的字符串,则PHP utf8_encode将失败或返回垃圾。

最简单的解决方案应该是让数据库/驱动程序使用CAST函数将值转换为正确的编码:https://www.ibm.com/support/knowledgecenter/SSEPEK_11.0.0/sqlref/src/tpc/db2z_castspecification.html

尝试更改您的查询,让DB2直接将所有内容转换为UTF-8,并省略utf8_encode调用。这可以通过将查询更改为:

来完成
SELECT CAST(NAME AS VARCHAR(255) CCSID 1208) FROM DATABASE_EXAMPLE.TABLE_EXAMPLE

感谢Sergei关于IBM PUA的CCSID 1208的说明。我将CCSID UNICODE更改为CCSID 1208

我这里没有DB2,所以上面的查询是未经测试的。我不确定这是否会返回utf-8或utf-16 ..