Page 1 sur 1

Problème d'interaction UTF-8 (forcé dans php.ini) et latin1

Posté : 21 oct. 2007, 10:16
par Masahiro
Bonjour,


J'ai décidé de laisser un message ici après plusieurs heures à farfouiller un peu partout.

Mon serveur force l'utilisation de l'UTF-8 dans php.ini. Ici apparemment, ça pose problème.

Voici ma source (en partie) :
if (isset($_GET['step']) && $_GET['step'] == 1)
{
	$time_start = microtime(true);
	$i = 0;
	echo '<p>Insertion des <i>Kanji</i><br />';
	foreach ($xml->character as $char)
	{
		$i++;
		$literal = $char->literal;
		//$literal = utf8_to_html($char->literal);
		//$literal = mb_convert_encoding($char->literal, "latin1", "UTF-8");
		//mysql_query("SET NAMES 'latin1'");
		//$literal = utf8_decode($literal);
		echo $literal .'<br>';
		
		$sql = 'INSERT INTO `dico_kanji` ( `id` , `literal` ) VALUES (NULL , "'. $literal .'");';
		if (isset($_GET['action']) && $_GET['action'] == 1) $req = @mysql_query($sql) or die('Erreur SQL !<br>'. $sql .'<br>'. mysql_error());
		//echo '<img src="../images/bar.gif" alt="bar"/>';
	}
	$time_end = microtime(true);
	$time = round($time_end - $time_start,2);
	echo '<br />
	<i>Kanji</i> insérés avec succès ('. $i .' entrées) <font color="grey">'. $time .' sec.</font></p>';
	if (isset($_GET['action']) && $_GET['action'] == 1)
	{
		echo '<a href="./kanjidic2.php?action=1&step=2">Etape suivante</a>';
	}
	else
	{
		echo '<a href="./kanjidic2.php?step=2">Etape suivante</a>';
	}
}

Alors, je vous explique ma démarche :

Il y a un document XML que je dois parser, il n'y a pas de souci à ce niveau. Je le fais avec simpleXML.

Les entrées "literal" sont des caractères japonais encodées en UTF-8. Apparemment, il y a un souci quand l'UTF-8 est forcé, soit disant il part du principe que l'encodage de base est latin1 (cp1252) et du coup, il encode une seconde fois en UTF-8, ce qui donne un résultat incorrect.

Voici plus de détail sur le problème :

http://dev.mysql.com/doc/refman/5.1/en/ ... -sets.html


Ils indiquent de faire un dump mais moi je ne veux pas faire ça ! Je veux convertir à la volée et injecter l'enregistrement dans la BDD.

Je suis sur que c'est trois fois rien à faire, mais j'en ai un peu marre. Merci de m'accorder un peu de votre temps !

Posté : 21 oct. 2007, 10:46
par Tracker
Salut,

Tu peux filer ton fichier XML et la stucture de ta table (create table ...) ?



Tracker.

Posté : 21 oct. 2007, 11:45
par Masahiro
Salut Tracker ! Merci de m'accorder un peu de ton temps.

Voici la structure :

Code : Tout sélectionner

-- Structure de la table `dico_kanji` -- CREATE TABLE `dico_kanji` ( `id` smallint(5) unsigned NOT NULL auto_increment, `literal` varchar(10) NOT NULL, `cp_type_ucs` char(4) NOT NULL, `cp_type_jis208` varchar(5) NOT NULL, `cp_type_jis212` varchar(5) NOT NULL, `cp_type_jis213` varchar(7) NOT NULL, `rad_type_classical` varchar(254) NOT NULL, `rad_type_nelson_c` varchar(255) NOT NULL, `misc_grade` varchar(255) NOT NULL, `misc_stroke_count` varchar(255) NOT NULL, `misc_var_type_jis208` varchar(5) NOT NULL, `misc_var_type_jis212` varchar(255) NOT NULL, `misc_var_type_jis213` varchar(255) NOT NULL, `misc_var_type_deroo` varchar(255) NOT NULL, `misc_var_type_njecd` varchar(255) NOT NULL, `misc_var_type_s_h` varchar(255) NOT NULL, `misc_var_type_nelson_c` varchar(255) NOT NULL, `misc_var_type_oneill` varchar(255) NOT NULL, `misc_var_type_ucs` varchar(255) NOT NULL, `dr_type_nelson_c` varchar(4) NOT NULL, `dr_type_nelson_n` varchar(4) NOT NULL, `dr_type_halpern_njecd` varchar(4) NOT NULL, `dr_type_halpern_kkld` varchar(4) NOT NULL, `dr_type_heisig` varchar(4) NOT NULL, `dr_type_gakken` varchar(4) NOT NULL, `dr_type_oneill_names` varchar(5) NOT NULL, `dr_type_oneill_kk` varchar(4) NOT NULL, `dr_type_moro` varchar(7) NOT NULL, `dr_type_m_vol` varchar(255) NOT NULL, `dr_type_m_page` varchar(4) NOT NULL, `dr_type_henshall` varchar(4) NOT NULL, `dr_type_sh_kk` varchar(4) NOT NULL, `dr_type_sakade` varchar(255) NOT NULL, `dr_type_jf_cards` varchar(255) NOT NULL, `dr_type_henshall3` varchar(255) NOT NULL, `dr_type_tutt_cards` varchar(255) NOT NULL, `dr_type_crowley` varchar(255) NOT NULL, `dr_type_kanji_in_context` varchar(4) NOT NULL, `dr_type_busy_people` varchar(255) NOT NULL, `dr_type_kodansha_compact` varchar(4) NOT NULL, `q_type_skip` varchar(255) NOT NULL, `q_type_sh_desc` varchar(9) NOT NULL, `q_type_four_corner` varchar(6) NOT NULL, `q_type_deroo` varchar(255) NOT NULL, `q_type_misclass` varchar(255) NOT NULL, `r_type_pinyin` varchar(8) NOT NULL, `r_type_korean_r` varchar(255) NOT NULL, `r_type_korean_h` varchar(255) NOT NULL, `r_type_ja_on` varchar(255) NOT NULL, `r_type_ja_kun` varchar(80) NOT NULL, `meaning_m_lang_en` varchar(167) NOT NULL, `meaning_m_lang_es` varchar(153) NOT NULL, `meaning_m_lang_pt` varchar(146) NOT NULL, `meaning_m_lang_de` varchar(0) NOT NULL, `reading_nanori` text NOT NULL, PRIMARY KEY (`id`), KEY `literal` (`literal`), KEY `cp_type_ucs` (`cp_type_ucs`), KEY `cp_type_208` (`cp_type_jis208`), KEY `cp_type_212` (`cp_type_jis212`), KEY `cp_type_213` (`cp_type_jis213`), KEY `rad_type_classical` (`rad_type_classical`), KEY `rad_type_nelson_c` (`rad_type_nelson_c`), KEY `misc_grade` (`misc_grade`), KEY `misc_stroke_count` (`misc_stroke_count`), KEY `misc_var_type_jis208` (`misc_var_type_jis208`), KEY `misc_var_type_jis212` (`misc_var_type_jis212`), KEY `misc_var_type_jis213` (`misc_var_type_jis213`), KEY `misc_var_type_deroo` (`misc_var_type_deroo`), KEY `misc_var_type_njecd` (`misc_var_type_njecd`), KEY `misc_var_type_s_h` (`misc_var_type_s_h`), KEY `misc_var_type_nelson_c` (`misc_var_type_nelson_c`), KEY `misc_var_type_oneill` (`misc_var_type_oneill`), KEY `misc_var_type_ucs` (`misc_var_type_ucs`), KEY `dr_type_nelson_c` (`dr_type_nelson_c`), KEY `dr_type_nelson_n` (`dr_type_nelson_n`), KEY `dr_type_halpern_njecd` (`dr_type_halpern_njecd`), KEY `dr_type_halpern_kkld` (`dr_type_halpern_kkld`), KEY `dr_type_heisig` (`dr_type_heisig`), KEY `dr_type_gakken` (`dr_type_gakken`), KEY `dr_type_oneill_names` (`dr_type_oneill_names`), KEY `dr_type_oneill_kk` (`dr_type_oneill_kk`), KEY `dr_type_moro` (`dr_type_moro`), KEY `dr_type_m_vol` (`dr_type_m_vol`), KEY `dr_type_m_page` (`dr_type_m_page`), KEY `dr_type_henshall` (`dr_type_henshall`), KEY `dr_type_sh_kk` (`dr_type_sh_kk`), KEY `dr_type_sakade` (`dr_type_sakade`), KEY `dr_type_jf_cards` (`dr_type_jf_cards`), KEY `dr_type_henshall3` (`dr_type_henshall3`), KEY `dr_type_tutt_cards` (`dr_type_tutt_cards`), KEY `dr_type_crowley` (`dr_type_crowley`), KEY `dr_type_kanji_in_context` (`dr_type_kanji_in_context`), KEY `dr_type_kodansha_compact` (`dr_type_kodansha_compact`), KEY `q_type_skip` (`q_type_skip`), KEY `q_type_sh_desc` (`q_type_sh_desc`), KEY `q_type_four_corner` (`q_type_four_corner`), KEY `q_type_deroo` (`q_type_deroo`), KEY `r_type_pinyin` (`r_type_pinyin`), KEY `r_type_korean_r` (`r_type_korean_r`), KEY `r_type_korean_h` (`r_type_korean_h`), KEY `r_type_ja_on` (`r_type_ja_on`), KEY `r_type_ja_kun` (`r_type_ja_kun`), KEY `dr_type_busy_people` (`dr_type_busy_people`), KEY `q_type_misclass` (`q_type_misclass`) ) ENGINE=MyISAM AUTO_INCREMENT=16582 DEFAULT CHARSET=utf8 AUTO_INCREMENT=16582 ;

Concernant le XML, il est un peu gros (15 Mo), mais ça devrait aller vite à l'époque du haut débit :-)

http://www.grossebertha.net/database/di ... jidic2.xml (note le super nom de domaine)

Posté : 21 oct. 2007, 15:56
par Tracker
Re,

Bon j'ai mis un peu de temps, l'entête de ton fichier xml ne contient pas la balise 'encoding', mais ça n'a pas d'incidence quand tu charges le fichier via SimpleXML.

En fait tu oublies simplement d'indiquer à MySQL l'encodage des caractères que tu lui transmets.
J'ai fait un test qui fonctionne avec le code suivant:
header('Content-type: text/html; charset=utf-8');
$cnx = mysql_connect('localhost','root','');
mysql_select_db('test1',$cnx);

//Ligne à ajouter <<--------------------------------------------
mysql_query("set names 'utf8'");
	
$time_start = microtime(true);
$i = 0;

echo '<p>Insertion des <i>Kanji</i><br />';

$xml = simplexml_load_file('c:\\downloads\\kanjidic2.xml');
foreach ($xml->character as $char)
{
    $i++;
    $literal = $char->literal;
    echo $literal.'<br/>';
        
    $sql = 'INSERT INTO `dico_kanji` (`literal` ) VALUES ("'. $literal .'");';
    $req = mysql_query($sql) or die('Erreur SQL !<br>'. $sql .'<br>'. mysql_error());
}
$time_end = microtime(true);
$time = round($time_end - $time_start,2);

echo '<br />
<i>Kanji</i> insérés avec succès ('. $i .' entrées) <font color="grey">'. $time .' sec.</font></p>';
?>
Par contre tes caractères ne sont pas forcement visibles (remplacés par des carrés dans IE, ou des ? dans FF) si aucun glyph correspondant n'est disponible dans la police d'affichage.
Les Kanjis sont utilisables avec cette police

Rq1:
Un truc est étrange: tous tes champs en base sont NOT NULL, sans valeur par défaut, et on arrive quand même à inserer des lignes en ne donnant que le champ 'litéral' ??!! C'est sûrement le moteur MyISAM qui le permet, c'est n'importe quoi...

Rq2:
Attention à enregistrer ton code php en uft8, sinon les caractères accentuées tapés en dur à l'intérieur seront érronnés.


Tracker.

Posté : 25 oct. 2007, 12:55
par Masahiro
Re-bonjour,


Je n'ai pas eu le temps de m'y mettre ces jours-ci. Ton script fonctionne parfaitement, merci pour ton aide une fois de plus.

J'espère que ça servira à d'autres.

Posté : 28 oct. 2007, 10:42
par Masahiro
Une petite remarque supplémentaire que j'ai remarqué après coup. Ca peut sembler évident aux anciens mais je ne savais pas que :

ISO-8859-1 = latin1 = cp1252


Je pensais que l'iso était encore autre chose, et ça m'a posé problème.

Posté : 28 oct. 2007, 10:49
par Tracker
Une petite remarque supplémentaire que j'ai remarqué après coup. Ca peut sembler évident aux anciens mais je ne savais pas que :

ISO-8859-1 = latin1 = cp1252


Je pensais que l'iso était encore autre chose, et ça m'a posé problème.
pas tout à fait,
je crois que c'est: ISO-8859-1 = latin1_swedish = cp1252
c'est pour ça que c'est le réglage par défaut de mysql


Tracker.