Page 1 sur 2

UTF8izer : pour convertir en UTF-8 tous les fichiers ISO d'un dossier

Posté : 01 nov. 2008, 15:40
par albat
Bonjour,

Pour la migration d'un site d'ISO-8859-1 vers UTF-8,
j'ai eu besoin de convertir tous les fichiers HTML et PHP.

Pour cela, il faut :
- changer le jeu de caractères utilisés et l'encodage de chaque fichier
- remplacer les entités HTML ("é") par leurs caractères correspondants ("é")

Voici le script qui fait tout ça...

:!: N'oubliez pas de créer deux sous-dossiers /iso et /utf8
(paramétrables au début du script : lignes 3 et 4).
- le dossier /iso contient bien entendu les fichiers originaux
- le dossier /utf8 accueillera les copies de ces fichiers converties en UTF-8
J'ai choisi de procéder ainsi plutôt que par réécriture/écrasement par souci de sécurité.

:!: Par défaut, j'ai choisi de ne traiter que les fichiers d'extensions .php et .htm.
N'oubliez pas de modifier ce choix si nécessaire (ligne 10)

Merci à Calimero pour son coup de main au débuggage. :merci:
<table summary="UTF8_izer">
<?php
$dossier_iso  = 'iso';
$dossier_utf8 = 'utf8';

$handle = opendir($dossier_iso);
while ($file = readdir($handle))
      { if (is_file($dossier_iso.'/'.$file))
           { $extension = substr($dossier_iso.'/'.$file, -3, 3);
             if ($extension=='php' || $extension=='htm')
                { echo '<tr><td>'.$file.'</td>'."\n";
                  $contenu = file_get_contents($dossier_iso.'/'.$file);
                  if ($contenu)
                     { $contenu_new = $contenu;
                       $contenu_new = utf8_encode($contenu_new);
                       $contenu_new = html_entity_decode($contenu_new,ENT_NOQUOTES,'UTF-8');
                       $conversion = file_put_contents($dossier_utf8.'/'.$file,$contenu_new);
                       echo '<td>'.($conversion ? 'OK' : '-----').'</td></tr>'."\n";
                     }
                     else
                     { echo '<td>Conversion non effectuée</td></tr>'."\n";
                     }
                }  
           }
      }
closedir($handle);
?>
</table>

Re: UTF8izer : pour convertir en UTF-8 tous les fichiers ISO

Posté : 01 nov. 2008, 15:47
par albat
Également disponible en version "light" (ou condensée) : traitement seul, aucun affichage. :langue:
$dossier_iso  = 'iso';
$dossier_utf8 = 'utf8';

$handle = opendir($dossier_iso);
while ($file = readdir($handle))
      { if (is_file($dossier_iso.'/'.$file))
           { $extension = substr($dossier_iso.'/'.$file, -3, 3);
             if ($extension=='php' || $extension=='htm')
                { file_put_contents($dossier_utf8.'/'.$file,html_entity_decode(utf8_encode(file_get_contents($dossier_iso.'/'.$file)),ENT_NOQUOTES,'UTF-8'));
                }  
           }
      }
closedir($handle);

Posté : 02 nov. 2008, 17:31
par SpintroniK
Très bien, merci !

D'un point de vue personnel, j'aurais créé un tableau contenant toutes les extensions des fichiers à traiter car par exemple, j'ai aussi des fichiers css, .tpl...

En tout cas, c'est très bien fait, merci.

Posté : 03 nov. 2008, 01:20
par Hywan
Hey :),

Je voulais signaler un programme dont j'ai parlé il y a peu dans un sujet (voir Problème complexe formulaire). Il s'agit du programme Charco. Si j'ai bien compris, il s'agit juste de mettre une interface graphique sur la célèbre (et géniale) commande iconv disponible sur toutes les plates-formes Unix digne de ce nom (voir iconv(1)).

Je ne sais pas si le programme traite les dossiers, mais la commande iconv non. Toutefois, on peut réaliser la même chose avec un petit script Shell. Très naïvement on aurait :

Code : Tout sélectionner

#!/bin/bash if [ $# -lt 3 ]; then echo "Usage : $0 <from> <to> <directory>." exit 1 fi if [ ! -d $3 ]; then echo "Directory $3 does not exist." exit 2 fi from=$1 to=$2 directory=$3 for i in `ls $directory`; do if [ -f $i ]; then echo "Convert $i." iconv -f $from -t $to $i > $i.conv fi done echo "Done."
On peut largement l'améliorer (en précisant un dossier d'arrivée par exemple, ici tous les fichiers encodés portent l'extension .conv), mais l'idée est là. On peut aussi ne scanner que les .php et les .htm(l ?) tout comme toi. Ce n'est qu'un brouillon.
On l'utiliserait de cette façon :

Code : Tout sélectionner

$ chmod +x conv $ ./conv latin1 utf8 dir
PS : vite fait et même pas testé :oops:.

Posté : 04 janv. 2009, 20:08
par SiMax
Merci pour l'outil !

J'ai un petit problème :

Code : Tout sélectionner

Warning: cannot yet handle MBCS in html_entity_decode()! in c:\program files\easyphp\www\convert.php on line 16
Que faut-il faire ? Mon répertoire est organisé comme cela :

- WWW
- - iso
- - - fichier1.php
- - - fichier2.php
- - uft8
- - convert.php

Posté : 04 janv. 2009, 22:42
par momox
Passe sous WAMP ;)

Posté : 05 janv. 2009, 17:23
par SiMax
D'accord ! Merci :) Je vais essayer ça.

Posté : 01 mars 2009, 13:57
par SpintroniK
Très bon le script, merci beaucoup :D .

Je note juste un petit problème concernant l'extension des fichiers, en effet, j'utilise des fichiers .html donc l'extension contient 4 caractères, ce qui m'a obligé à donner l'extension tml au script.
Donc pourquoi ne pas utiliser pathinfo (http://fr2.php.net/pathinfo) à la place du substr :wink: ?

Re: UTF8izer : pour convertir en UTF-8 tous les fichiers ISO d'u

Posté : 12 août 2009, 11:07
par albat
Ben... parce que j'ai développé cet outil en fonction de mes besoins personnels
et ne me suis donc pas attaché à envisager les autres cas. :oops:

Mais ce code est ouvert à toute amélioration. :pouce:

Re: UTF8izer : pour convertir en UTF-8 tous les fichiers ISO d'u

Posté : 21 nov. 2009, 13:37
par regis-92
Bonjour,

Pour ma part, le script ne fonctionne pas... et je n'ai aucun message d'erreur, juste une page blanche.

J'ai place ce script dans un rep appelé utils sur mon site, j'y ai bien créé les 2 ss-reps iso et utf8, j'ai placé un fichier html dans le ss-rep iso, lancé le script mais je n'ai rien dans le ss-rep utf8...

Ce n'est pas un problème de droits (777 de partout...)

D'où cela peut-il venir ?

Merci pour toute aide :)
Regis

Re: UTF8izer : pour convertir en UTF-8 tous les fichiers ISO d'u

Posté : 25 nov. 2009, 12:51
par Truc
J'ai place ce script dans un rep appelé utils sur mon site, j'y ai bien créé les 2 ss-reps iso et utf8, j'ai placé un fichier html dans le ss-rep iso, lancé le script mais je n'ai rien dans le ss-rep utf8...
peut être...
Très bon le script, merci beaucoup :D .

Je note juste un petit problème concernant l'extension des fichiers, en effet, j'utilise des fichiers .html donc l'extension contient 4 caractères, ce qui m'a obligé à donner l'extension tml au script.
Donc pourquoi ne pas utiliser pathinfo (http://fr2.php.net/pathinfo) à la place du substr :wink: ?

Re: UTF8izer : pour convertir en UTF-8 tous les fichiers ISO d'u

Posté : 25 nov. 2009, 13:04
par regis-92
Ah oui en effet... il fallait utiliser des fichiers htm et non pas html !

Bien vu merci :D

Re: UTF8izer : pour convertir en UTF-8 tous les fichiers ISO d'u

Posté : 29 juil. 2010, 15:13
par jojolapine
Hello hello,

Pour des besoins particulier, j'ai complètement refondu le système, pour ne garder que les fonctions de conversions d'albat.

Au programme des fonctionnalités:
  • Traitement récursif et conservation de l'arborescence
  • Choix des extensions à traiter (sous forme de tableau)
  • Choix des répertoires à exclure ( '.', '..', dossiers svn, librairies externes...)
  • Traitement des fichiers vides (simple création du fichier dans le répertoire cible
  • Compteur de nombre de fichiers (je suis arrivé à 1244 pour mon projet et ça roule :) )
J'ai traité le contenu des fichiers lignes à lignes, car j'en avais un de 405 ... Mo :-°
Donc celà permet combiné à une modification du paramètre memory_limit (php.ini) et du timeout de traiter de très gros fichiers!
(bon le processeur en prend un coup :) )

Limitations:
  • Attention à ne prendre pour argent comptant le dossier de destination comme votre projet tout frais tout beau!
    En effet les dossiers et extensions exclus ne sont pas copiés dans le répertoire source. Il vous faudra faire un "merge" des deux versions
  • Attention aux droits des dossiers!
Voici le code:
<table summary="UTF8_izer">

<?php

// nécessaire pour les gros fichiers
// il peut être aussi utile de changer le memory_limit dans le php.ini
set_time_limit(0);


/**
 * utf8izer
 *
 * Permet de transformer les fichiers d'un répertoire récursivement
 * en gardant l'arborescence.
 *
 * @param string  $repertoire     le répertoire à traiter
 * @param string  $dossier_utf8   le dossier de destination
 * @param array   $extensions     extensions à traiter
 * @param array   $exclude_dir    répertoires à exclure
 * @param bool    $first_time     indique si la fonction est utilisé
 *                                la première fois, afin d'initialiser
 *                                $dossier_iso et $compteur
 */
function utf8izer($repertoire,$dossier_utf8,$extensions=array('php','html'),$exclude_dir=array('.','..'),$first_time=true)
{
    // Compteur du nombre de fichier traité
    static $compteur;

    // Dossier iso, afin d'effectuer les remplacement de chemins
    static $dossier_iso;

    // Si premier appel, initialisation
    if($first_time){
      $compteur = 1;
      $dossier_iso = $repertoire;
    }

    // Ouverture du repertoire
    $le_repertoire = opendir($repertoire) or die("Erreur le repertoire $repertoire existe pas");

    // Lecture de son contenu
    while($fichier = @readdir($le_repertoire))
    {

        // Si dossier exclu, on passe à l'entrée suivante
        if (in_array($fichier,$exclude_dir)) continue;

        // on prépare le répertoire cible
        $repertoire_cible = str_replace($dossier_iso,$dossier_utf8,$repertoire);

        // Si repertoire
        if(is_dir($repertoire.'/'.$fichier))
        {

            // si il n'existe pas, on essaye de créer le répertoire
            if (!is_dir($repertoire_cible) && !mkdir($repertoire_cible.'/'.$fichier, 0777, true)) {
                die('Echec lors de la création des répertoires...<br />'.$repertoire_cible.'/'.$fichier);
            }

            // et on descend plus profond dans l'arborescence
            utf8izer($repertoire.'/'.$fichier,$dossier_utf8,$extensions,$exclude_dir,false);
        }
        // Si fichier
        else
        {
          // si il n'éxiste pas déjà dans le répertoire cible
          if(!is_file($repertoire_cible.'/'.$fichier)){

            // Récupération des infos sur le fichier
            $file_infos = pathinfo($repertoire.'/'.$fichier);

            // Si extension à traiter
            if(in_array($file_infos['extension'],$extensions)){

              echo  '<tr>'.PHP_EOL.
                      '<td>'.$compteur.'</td>'.PHP_EOL.
                      '<td>'.$repertoire.'/'.$fichier.'</td>'.PHP_EOL;

              // récupération du contenu sous forme de tableau pour
              // pouvoir passer le contenu ligne par ligne aux fonctions
              // de transformation, car si le fichier est trop gros
              // elles ne fonctionnent plus.
              $contenu_array = file($repertoire.'/'.$fichier);

              // Si récupération OK
              if ($contenu_array!==false){

                // taille du tableau
                $contenu_size = count($contenu_array);

                // Si non vide
                if(!empty($contenu_array)){

                  // initialisation du nouveau contenu
                  $contenu_new = '';

                  // parcours de l'ancien contenu
                  for($i = 0; $i<$contenu_size;$i++){

                    // transformation de la ligne
                    $contenu_tmp = $contenu_array[$i];
                    $contenu_tmp = utf8_encode($contenu_tmp);
                    $contenu_tmp = html_entity_decode($contenu_tmp,ENT_NOQUOTES,'UTF-8');

                    // ajout au nouveau contenu
                    $contenu_new.=$contenu_tmp;
                  }

                  // test si le dossier existe déjà
                  if (!is_dir($repertoire_cible) && !mkdir($repertoire_cible, 0777, true)) {
                      die('Echec lors de la création des répertoires...<br />'.$repertoire_cible.'/'.$fichier);
                  }

                  // écriture dans le fichier cible du résultat final
                  $conversion = file_put_contents($repertoire_cible.'/'.$fichier,$contenu_new);
                }
                // création fichier vide
                else {
                  $conversion = fopen($repertoire_cible.'/'.$fichier,'w');
                }
                echo '<td>'.($conversion!==false ? 'OK' : 'Conversion avortée...<br />('.$repertoire_cible.'/'.$fichier.')').'</td></tr>'."\n";
              }
              // récupération contenu incorrecte
              else {

                echo '<td>Impossible de récupérer le contenu...</td></tr>'."\n";
              }

              // on incrémente le nombre de fichiers traités
              $compteur++;
            }
          }
        }
    }

    closedir($le_repertoire);
}

$dossier_iso  = '/path/to/myproject';

$dossier_utf8 = '/path/to/myproject_utf8';


$exclude_dir=array(".","..",".svn","jpgraph","phpToPDF","nbproject");
$extensions = array('php','htm','css','tpl','js','sql','html');


utf8izer($dossier_iso,$dossier_utf8,$extensions,$exclude_dir);


?>

</table>


Re: UTF8izer : pour convertir en UTF-8 tous les fichiers ISO d'u

Posté : 31 juil. 2010, 19:58
par stealth35
tu peux aussi utiliser RecursiveDirectoryIterator pour lire plus simplement les dossiers (et pourquoi pas coupler a un globiterator aussi) :wink: , ensuite tu peux aussi utiliser les filtres de stream, grâce au filter convert, tu peux ouvrir le fichier direct en utf-8 et avec ton html_entity_decode

Re: UTF8izer : pour convertir en UTF-8 tous les fichiers ISO d'u

Posté : 02 août 2010, 04:54
par stealth35
tu peux aussi utiliser RecursiveDirectoryIterator pour lire plus simplement les dossiers (et pourquoi pas coupler a un globiterator aussi) :wink: , ensuite tu peux aussi utiliser les filtres de stream, grâce au filter convert, tu peux ouvrir le fichier direct en utf-8 et avec ton html_entity_decode
ca pourrait donner un truc du genre :
class html_entity_decode_filter extends php_user_filter
{
    public function filter($in, $out, &$consumed, $closing)
    {        
        while($bucket = stream_bucket_make_writeable($in))
        {
              $bucket->data = html_entity_decode($bucket->data, ENT_NOQUOTES, 'UTF-8');
              $consumed += $bucket->datalen;
              stream_bucket_append($out, $bucket);
        }
        
        return PSFS_PASS_ON;
    }    
}

class IgnoreFilter extends FilterIterator
{
    private $ext_filter;
    private $dir_filter;
    
    public function __construct($iterator, array $ext_filter, array $dir_filter)
    {
        parent::__construct($iterator);
        $this->ext_filter = $ext_filter;
        $this->dir_filter = $dir_filter;
    }
    
    public function accept()
    {            
        if($this->current()->isDir() && !$this->current()->isDot())
        {
            return !in_array($this->current()->getFilename(), $this->dir_filter);
        }
        
        if($this->current()->isFile())
        {
            if(!empty($this->ext_filter))
            {
                return in_array(pathinfo($this->current()->getFilename(), PATHINFO_EXTENSION), $this->ext_filter);
            }
            else
            {
                return true;
            }
        }
    }
}

function utf8izer($dest, $path, array $ext_filter = array(), array $dir_filter = array())
{
    stream_filter_register('string.html_entity_decode', 'html_entity_decode_filter');        

    $realpath = realpath('../phpmyadmin');
    $dir      = new RecursiveDirectoryIterator($realpath);
    $filter   = new IgnoreFilter(new RecursiveIteratorIterator($dir), $ext_filter, $dir_filter);    
    
    foreach($filter as $file)
    {
        $filename = str_replace($path, '', $file->getRealPath());
        $dirname  = pathinfo($filename, PATHINFO_DIRNAME);
        
        if(!file_exists($dest . $dirname))
        {
            mkdir($dest . $dirname, 0777, true);
        }
        
        $copy = copy('php://filter/read=string.html_entity_decode|convert.iconv.ISO-8859-1%2FUTF-8/resource=' . $file->getRealPath(), $dest . $filename);
        //var_dump($copy);    
    }
}

utf8izer('test4', '../phpmyadmin', array('php'));
au niveau de l'approche c'est les filter de stream simplement associé a la fonction copy, on copie le fichier en lui appliquant des filtres (ici html_entity_decode et un iconv), le html_entity_decode n'existe pas donc on doit le creer, pourl a liste des fichier c'est un RecursiveDirectoryIterator coupler a un filtre perso (mais on aurrait pu utiliser RegexIterator), voila plus qu'a boucler le copy sur l'iterator :wink:
j'ai fais un test sur phpmyadmin, on arrive a 7 sec (contre 28 sec)