2010-07-22 8 views
3

J'ai des fichiers texte que je suis en train de transformer avec un script Perl sous Windows. Les fichiers texte semblent normaux dans Notepad +, mais toutes les expressions rationnelles de mon script ne correspondaient pas. Puis j'ai remarqué que lorsque j'ouvre les fichiers texte dans NotePad +, la barre d'état dit "UCS-2 Little Endia" (sic). Je suppose que cela correspond à l'encodage UCS-2LE. Donc, j'ai créé « readFile » et « WRITEFILE » sous-marins en Perl, comme ceci:Unicode en Perl ne fonctionne pas

use PerlIO::encoding; 

my $enc = ':encoding(UCS-2LE)'; 

sub readFile { 
    my ($fName) = @_; 
    open my $f, "<$enc", $fName or die "can't read $fName\n"; 
    local $/; 
    my $txt = <$f>; 
    close $f; 
    return $txt; 
} 

sub writeFile { 
    my ($fName, $txt) = @_; 
    open my $f, ">$enc", $fName or die "can't write $fName\n"; 
    print $f $txt; 
    close $f; 
} 

my $fName = 'someFile.txt'; 

my $txt = readFile $fName; 
# ... transform $txt using s/// ... 
writeFile $fName, $txt; 

Maintenant le match de regexes (bien que je pense moins souvent), mais la sortie contient de longues chaînes de caractères asiatiques prospectifs entrecoupées longues chaînes du texte correct. Mon code est-il faux? Ou peut-être que Notepad + est faux à propos de l'encodage? Comment dois-je procéder?

+0

fournir des données de test, un hexdump supplémentaire est une bonne idée. Afficher le code * complet * qui provoque le problème. Si vous ne nous permettez pas de reproduire le problème, nous ne pouvons que spéculer. – daxim

+0

@daxim: le code ici est raisonnablement complet, la seule raison pour laquelle je ne peux pas le vérifier est parce que je n'ai pas le bloc-notes + éditeur pour comparer. À la conjecture, c'est un problème de nomenclature. –

Répondre

2

OK, je l'ai compris. Le problème était provoqué par une déconnexion entre la traduction de codage effectuée par le paramètre "encoding ..." de l'appel "open" et la traduction CRLF par défaut effectuée par Perl sous Windows. Ce qui semblait se produire était que LF était en cours de traduction en CRLF sur la sortie après le codage avait déjà été fait, ce qui a supprimé la "parité" du codage à 16 bits pour la ligne suivante. Une fois la ligne suivante atteinte, la "parité" a été remise. Cela expliquerait les «longues chaînes de caractères à l'allure asiatique entrecoupées de longues chaînes du bon texte» ... toutes les autres lignes étaient en train d'être bousillées.

Pour corriger, je pris le paramètre de codage dans mon "ouvert" appel et a ajouté un appel "binmode", comme suit:

open my $f, $fName or die "can't read $fName\n"; 
binmode $f, ':raw:encoding(UCS-2LE)'; 

binmode a apparemment un concept de "couches" I/O la manipulation est quelque peu compliquée.

Une chose que je n'arrive pas à comprendre est comment récupérer ma traduction CRLF. Si je laisse de côté: raw ou ajouter: crlf, le problème de "parité" revient. J'ai aussi essayé de commander de nouveau et je n'arrive pas à le faire fonctionner.

(j'ai ajouté cela comme une question distincte: CRLF translation with Unicode in Perl)

Questions connexes