2010-03-17 19 views
7

Sto usando osql per eseguire diversi script sql su un database e quindi ho bisogno di guardare il file dei risultati per verificare se si sono verificati errori. Il problema è che Perl non sembra gradire il fatto che i file dei risultati siano Unicode.Come posso aprire un file Unicode con Perl?

ho scritto un piccolo script di test per provarlo e l'uscita viene fuori tutto gorgheggiava:

$file = shift; 

open OUTPUT, $file or die "Can't open $file: $!\n"; 
while (<OUTPUT>) { 
    print $_; 
    if (/Invalid|invalid|Cannot|cannot/) { 
     push(@invalids, $file); 
     print "invalid file - $inputfile - schedule for retry\n"; 
     last; 
    }    
} 

Tutte le idee? Ho provato la decodifica usando decode_utf8 ma non fa differenza. Ho anche provato a impostare la codifica quando si apre il file.

Penso che il problema potrebbe essere che osql inserisce il file risultato in formato UTF-16, ma non ne sono sicuro. Quando apro il file nel textpad mi dice semplicemente "Unicode".

Edit: Usando Perl v5.8.8 Edit: Hex discarica:

file name: Admin_CI.User.sql.results 
mime type: 

0000-0010: ff fe 31 00-3e 00 20 00-32 00 3e 00-20 00 4d 00 ..1.>... 2.>...M. 
0000-0020: 73 00 67 00-20 00 31 00-35 00 30 00-30 00 37 00 s.g...1. 5.0.0.7. 
0000-0030: 2c 00 20 00-4c 00 65 00-76 00 65 00-6c 00 20 00 ,...L.e. v.e.l... 
0000-0032: 31 00           1. 
+1

Che aspetto ha l'output? Potete fornire un hex + dump ascii all'inizio del file? –

+0

L'output è simile al seguente: ■ 1> 2> M s g 1 5 1 5 1, L e v e l 1 6, S t a t e 1 –

+0

Cosa utilizzerei per fornire un dump hex + ascii all'inizio del file? –

risposta

15

Il file è presumibilmente nel formato UCS2-LE (o nel formato UTF-16).

C:\Temp> notepad test.txt 

C:\Temp> xxd test.txt 
0000000: fffe 5400 6800 6900 7300 2000 6900 7300 ..T.h.i.s. .i.s. 
0000010: 2000 6100 2000 6600 6900 6c00 6500 2e00 .a. .f.i.l.e...

Quando si apre tale file per la lettura, è necessario specificare la codifica:

#!/usr/bin/perl 

use strict; use warnings; 

my ($infile) = @ARGV; 

open my $in, '<:encoding(UCS-2le)', $infile 
    or die "Cannot open '$infile': $!"; 

Si noti che il fffe all'inizio è la BOM.

+1

Era esattamente quello che stavo cercando quando chiedevo la discarica. :) –

+0

Grazie - in realtà era UTF-16. –

+1

UCS-2le è molto, molto vicino a UTF-16: http://en.wikipedia.org/wiki/UTF-16/UCS-2 –

4

Provare ad aprire il file con uno strato IO specificato, per esempio :

Vedere perldoc open per ulteriori informazioni.

7

La risposta è nella documentazione per open, che indica anche perluniintro. :)

open my $fh, '<:encoding(UTF-16LE)', $file or die ...; 

è possibile ottenere un elenco dei nomi delle codifiche che il vostro perl supporta:

% perl -MEncode -le "print for Encode->encodings(':all')" 

Dopo di che, è a voi per scoprire che cosa la codifica del file è. È come se avessi aperto un file con una codifica diversa da quella predefinita, indipendentemente dal fatto che sia definita da Unicode o meno.

Abbiamo un capitolo in Effective Perl Programming che passa attraverso i dettagli.

0
# 
    # ----------------------------------------------------------------------------- 
    # Reads a file returns a sting , if second param is utf8 returns utf8 string 
    # usage: 
    # ($ret , $msg , $str_file) 
    #   = $objFileHandler->doReadFileReturnString ($file , 'utf8') ; 
    # or 
    # ($ret , $msg , $str_file) 
    #   = $objFileHandler->doReadFileReturnString ($file) ; 
    # ----------------------------------------------------------------------------- 
    sub doReadFileReturnString { 

     my $self  = shift; 
     my $file  = shift; 
     my $mode  = shift ; 

     my $msg  = {} ; 
     my $ret  = 1 ; 
     my $s   = q{} ; 

     $msg = " the file : $file does not exist !!!" ; 
     cluck ($msg) unless -e $file ; 

     $msg = " the file : $file is not actually a file !!!" ; 
     cluck ($msg) unless -f $file ; 

     $msg = " the file : $file is not readable !!!" ; 
     cluck ($msg) unless -r $file ; 

     $msg .= "can not read the file $file !!!"; 

     return ($ret , "$msg ::: $! !!!" , undef) 
      unless ((-e $file) && (-f $file) && (-r $file)); 

     $msg = '' ; 

     $s = eval { 
      my $string =(); #slurp the file 
      { 
       local $/ = undef; 

       if (defined ($mode) && $mode eq 'utf8') { 
        open FILE, "<:utf8", "$file " 
         or cluck("failed to open \$file $file : $!"); 
        $string = <FILE> ; 
        die "did not find utf8 string in file: $file" 
         unless utf8::valid ($string) ; 
       } 
       else { 
        open FILE, "$file " 
         or cluck "failed to open \$file $file : $!" ; 
        $string = <FILE> ; 
       } 
       close FILE; 

      } 
      $string ; 
     }; 

     if ([email protected]) { 
      $msg = $! . " " . [email protected] ; 
      $ret = 1 ; 
      $s = undef ; 
     } else { 
      $ret = 0 ; $msg = "ok for read file: $file" ; 
     } 
     return ($ret , $msg , $s) ; 
    } 
    #eof sub doReadFileReturnString 
Problemi correlati