Compter les caractères d’un fichier RTF

© Christian PAULUS. Document créé le 16 juillet 2010 , mis à jour le 16 juillet 2010.

L'idéal quand on veut être admiré, c'est d'être mort. Michel Audiard

Accueil du site > Astuces > MacOSX > Compter les caractères d’un fichier RTF

php / MacOsX 10.6 (Snow Leopard)

Script PHP à lancer en ligne de commande (Terminal.app), rtf_txtlen tente de convertir proprement le ou les fichiers donnés en paramètres en fichier ascii et en déduit la longueur du texte.

Par défaut, rtf_txtlen nettoie le texte avant de donner son résultat : il supprime les espaces en doubles et les lignes vides.

Le résultat est transmis sur la sortie standard. rtf_txtlen ne fait que lire les fichiers passés en paramètre. rtf_txtlen n’écrit ni ne modifie aucun fichier.

La fonction de conversion rtf2text inspirée du script de DonRamon, a été adaptée et corrigée pour certains caractères. Probablement à compléter d’ailleurs.

#!/usr/bin/php
<?php

// rtf_txtlen
// CP: Fri Jul 16 10:29:47 CEST 2010

// A utiliser en ligne de commande !

// Convertit le texte d'un fichier RTF
// et en donne la longueur
// ex:
//  monfichier.rtf  123456

// @see: http://habrahabr.ru/blogs/php/70119/

// @todo: tester un très gros fichier

$strip = $print = true;
$output = $help = false;
$usage = "Usage: {$argv[0]} [-h] [-s] [-o] [-n] [-?] file [file ...]";
$files = array();

if($argc > 1) {
        // Le premier arg est le nom de ce script
       
        // Ergo, passer à l'argument suivant
        while ($arg = next($argv)) {
                if ($arg[0] === '-') {
                        // option commence par '-'
                        switch ($arg) {
                                case '-h':
                                case '--help':
                                case '-help':
                                case '-?':
                                        $help = true;
                                        break;
                                case '-s':
                                        $strip = true;
                                        break;
                                case '-o':
                                        $output = true;
                                        break;
                                case '-n':
                                        $strip = false;
                                        break;
                        }
                }
                else {
                        $files[] = $arg;
                }
        }
}
else {
        fwrite(STDERR, $usage . PHP_EOL);
        exit(1);
}

if ($help) {
        fwrite(STDOUT, "
rtf_txtlen: Returns text len of RTF file.

{$usage}

Options:
        -h  print this help and quit
        -n  don't strip whitespaces and blank lines
        -s  strip whitespaces and blank lines
        -o  output file convertion to stdout
       
        file        RTF filename

");
        exit();
}

// Certains éléments précisent la forme
// de la page (couleur, fonte)
// ne sont pas du vrai contenu.

/*
* rtf_isPlainText()
* @param: $s string
* @return: true si c'est du vrai contenu
*/
function rtf_isPlainText($s) {
       
        static $n_eviter;
       
        $eviter = array(
                '*'
                , 'author'
                , 'info'
                , 'fonttbl'
       // Color Table
                , 'colortbl'
       // Custom XML Data Properties
                , 'datastore'
                , 'themedata'
                // oOo use stylesheet
                , 'stylesheet'
                );
        if(!$n_eviter) {
                $n_eviter = count($eviter);
        }    
        for ($i = 0; $i < $n_eviter; $i++) {
                if (!empty($s[$eviter[$i]])) return(false);
        }
        return(true);
}

/*
* Lire le fichier demandé
* et le convertir en texte.
* $param: $filename string
* @return: le texte converti
*/
function rtf2text($filename) {
        // Lire le fichier complet indiqué.
   // Attention aux très gros fichiers.
        $text = file_get_contents($filename);
   
   $text = trim($text);
   
        if (!strlen($text)) {
                return '';
        }

        $document = '';
        $stack = array();
        $j = -1;
   
   $chr_39 = chr(39);
   $chr_45 = chr(45);
        $chr_46 = chr(46);
   $chr_tab = "\t";
       
        // caractère par caractère
   for ($i = 0, $len = strlen($text);
        $i < $len;
                 $i++
       ) {
                $c = $text[$i];

                switch ($c) {
           
                        // si backslash, key word
                        case '\\':
               
               // lire ce qu'il y a après
                                $nc = $text[$i + 1];

                                $rtf_isPlainText = rtf_isPlainText($stack[$j]);
                               
                                if ($nc == '\\' && $rtf_isPlainText) {
                                        $document .= $nc;
                                }
                                elseif ($nc == '~' && $rtf_isPlainText) {
                                        $document .= ' ';
                                }
                                elseif ($nc == '_' && $rtf_isPlainText) {
                                        $document .= '-';
                                }
                                elseif ($nc == '*') {
                                        $stack[$j][$nc] = true;
                                }
                                elseif ($nc == "'") {
                                        $hex = substr($text, $i + 2, 2);
                                        if (rtf_isPlainText($stack[$j])) {
                                                $document .= chr(hexdec($hex));
                                        }
                                        $i += 2;
                                } elseif (
                                                  ($nc >= 'a' && $nc <= 'z')
                                                  || ($nc >= 'A' && $nc <= 'Z')
                                                 ) {
                                        $word = '';
                                        $param = null;

                                        for ($k = $i + 1, $m = 0;
                                                 $k < strlen($text);
                                                 $k++, $m++
                                                ) {
                                                $nc = $text[$k];
                                                if (
                                                        ($nc >= 'a' && $nc <= 'z')
                                                        || ($nc >= 'A' && $nc <= 'Z')
                                                   ) {
                                                        if (empty($param)) {
                                                                $word .= $nc;
                                                        }
                                                        else {
                                                                break;
                                                        }
                                                } elseif ($nc >= '0' && $nc <= '9')
                                                        $param .= $nc;
                                                elseif ($nc == '-') {
                                                        if (empty($param)) {
                                                                $param .= $nc;
                                                        }
                                                        else {
                                                                break;
                                                        }
                                                } else {
                                                        break;
                                                }
                                        }
                                        $i += $m - 1;

                                        $toText = '';
                                        switch (strtolower($word)) {
                                                // 'u' est suivi d'un paramètre
                       // en notation décimale d'un char unicode
                                                case 'u':
                                                        // skip utf8
                                                        $toText .= (($param < 256)
                                                                                ? chr($param) : ' ');
                                                        $ucDelta = @$stack[$j]['uc'];
                                                        if ($ucDelta > 0) {
                                                                $i += $ucDelta;
                                                        }
                                                        break;
                                                case 'par':
                                                case 'page':
                                                case 'column':
                                                case 'line':
                                                case 'lbr':
                                                        $toText .= PHP_EOL;
                                                        break;
                                                case 'emspace':
                                                case 'enspace':
                                                case 'qmspace':
                                                        $toText .= ' ';
                                                        break;
                                                case 'tab':
                                                        $toText .= $chr_tab;
                                                        break;
                                                case 'chdate':
                                                        $toText .= date("m.d.Y");
                                                        break;
                                                case 'chdpl':
                                                        $toText .= date("l, j F Y");
                                                        break;
                                                case 'chdpa':
                                                        $toText .= date("D, j M Y");
                                                        break;
                                                case 'chtime':
                                                        $toText .= date("H:i:s");
                                                        break;
                                                case 'emdash':
                                                case 'endash':
                                                        $toText .= $chr_45;
                                                        break;
                                                case 'bullet':
                                                        $toText .= $chr_46;
                                                        break;
                                                case 'lquote':
                                                case 'rquote':
                                                        $toText .= $chr_39;
                                                        break;
                                                default:
                                                        $stack[$j][strtolower($word)] =
                               empty($param)
                               ? true
                               : $param
                               ;
                                                break;
                                        }
                                        if (rtf_isPlainText($stack[$j])) {
                                                $document .= $toText;
                                        }
                                }

                                $i++;
                        break;
               
                        case '{':
                                array_push($stack, $stack[$j++]);
                                break;
                        case '}':
                                array_pop($stack);
                                $j--;
                                break;
                        case '\0':
                        case '\r':
                        case '\f':
                        case '\n':
                                break;
                        default:
                                if (rtf_isPlainText($stack[$j])) {
                                        $document .= $c;
                                }
                                break;
                }
        }

        return($document);
}

// traiter les fichiers donnés en paramètre
foreach($files as $file) {
       
        $len = null;
       
        if(is_readable($file)) {
       
       $result = rtf2text($file);
               
       if($result && $strip) {
           
                        // supprimer les espaces en trop
           // et les lignes vides
           $replace = array(
               '@[[:space:]]+@' => ' '
               , '@[\r\n]+@' => "\n"
               );
           $result = preg_replace(array_keys($replace)
                                  , $replace, $result);
       }
       
       if($output) {
           echo($result . PHP_EOL);
       }    
       
       if($print) {
           echo($file . "\t" . strlen($result) . PHP_EOL);
       }
   }
   else {
       fwrite(STDERR, 'Error: '.$file . ' unreadable' . PHP_EOL);
   }
}

Pour une utilisation plus souple, donnez les droits d’exécution (755) à ce script.

Problème de copier/coller ? Voici le script :

GZ - 2.2 ko
rtf_textlen

P.S. : unrtf, disponible sur le site gnu.org permet également de traduire un fichier RTF. Mais il ignore les accents (mode —text) et nécessite l’écriture dans un fichier.

A découvrir :

Plussoyez !

Répondre à cet article