Strasznie dużo czasu zmarnowałem usiłując zmienić kodowanie w bazie MySQL na UTF i dopasować skrypty Perla do tej zmiany.
Przestawienie MySQLa na UTF-8 jest proste:
mysql -u www -p --default-character-set=utf8
CREATE database kpma CHARACTER SET utf8 COLLATE utf8_bin;
Baza kpma
(użytkownika www
) będzie kodowana w UTF-8. Można też określić domyślne kodowanie wszystkich baz w pliku konfiguracji MySQLa, tj. w pliku /etc/mysql/my.cnf
(Debian):
[mysqld]
...
default-character-set = utf8
Trochę diagnostyki:
use kpma;
show variables like 'char%';
show table status;
select tytul from Utwor;
## jest OK -- na konsoli widać poprawne różne znaki diakrytyczne
Prawdziwa męka to było zmuszenie Perla do poprawnego traktowania danych UTF.
Trzy kluczowe dla poprawnego przetwarzania UTF sprawy to: 1) klauzula binmod
(patrz poniżej); 2) klauzula use utf8
(jeżeli skrypt zawiera napisy kodowane w UTF); 3) wpisy mysql_enable_utf8
/SET NAMES utf8
dotyczące MySQLa.
Szkielet skryptu Perla wygląda następująco:
#!/usr/bin/perl -w
# -*- coding: utf-8 -*- --
#
use strict;
use utf8; ## skrypt zawiera napisy kodowane UTF
use CGI qw(:standard);
use DBI;
binmode(STDOUT, ":utf8"); ## bez tego problemy z UTF
my $dbname = 'kpma'; ## Nazwa bazy
my $dbuser = 'www'; ## Nazwa użytkownika MySQL
my $dbpasswd = '??????'; ## Hasło dla $dbuser
my $dsn = "dbi:mysql:$dbname:localhost:3306";
my $dbh = DBI->connect($dsn, "$dbuser", "$dbpasswd", { ChopBlanks => 1 });
$dbh->{'mysql_enable_utf8'} = 1;
$dbh->do('SET NAMES utf8');
my $SQL = "SELECT tytul FROM Utwor WHERE id_kompozytor1 = 59 ORDER BY rok ";
##my $SQL = "SELECT nazwisko FROM Kompozytor ";
my $sth = $dbh->prepare($SQL);
$sth ->execute();
while ( my @piece = $sth->fetchrow_array() ) { print ">> @piece\n"; }
$dbh->disconnect || warn "Nie mogę zamknąć bazy $dbname\n";
Jeżeli skrypt korzysta (pobiera dane) z param()
to koniecznie należy zastosować funkcję decode_utf8
:
use Encode; ## param() trzeba dekodować
if (param()) {# -- Wypełniono formularz --
## http://ahinea.com/en/tech/perl-unicode-struggle.html
my $who = Encode::decode_utf8(param("kto"));
Działa nawet z dość starym Perlem:
$perl --version
This is perl, v5.10.0 built for arm-linux-gnueabi-thread-multi
Copyright 1987-2007, Larry Wall
Brak komentarzy:
Prześlij komentarz