2010-03-17 24 views
7

estoy usando osql para ejecutar varias secuencias de comandos SQL contra una base de datos y luego hay que buscar en el archivo de resultados para comprobar si se han producido errores. El problema es que a Perl no parece gustarle el hecho de que los archivos de resultados sean Unicode.¿Cómo puedo abrir un archivo Unicode con Perl?

escribí un pequeño script de prueba para probarlo y la salida salga todo trinó:

$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; 
    }    
} 

¿Alguna idea? He intentado decodificar usando decode_utf8 pero no hace la diferencia. También intenté configurar la codificación al abrir el archivo.

Creo que el problema podría ser que osql pone el archivo de resultados en formato UTF-16, pero no estoy seguro. Cuando abro el archivo en el teclado, me dice 'Unicode'.

Editar: Utilizando Perl v5.8.8 Editar: volcado Hex:

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

¿Cómo se ve la salida como? ¿Puedes proporcionar un volcado hexadecimal + ascii del comienzo del archivo? –

+0

de salida es como la siguiente: ■ 1> 2> M s g 1 5 1 5 1, L e v e l 1 6, S t t u 1 –

+0

¿Qué iba a utilizar para suministrar un hexágono + volcado ASCII del principio del archivo? –

Respuesta

15

Se supone que el archivo está en UCS2-LE (o 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...

Al abrir dicho archivo para su lectura, es necesario especificar la codificación:

#!/usr/bin/perl 

use strict; use warnings; 

my ($infile) = @ARGV; 

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

Tenga en cuenta que la fffe al principio es el BOM.

+1

Eso era exactamente lo que estaba buscando cuando pregunté por el vertedero. :) –

+0

Gracias - en realidad era UTF-16. –

+1

UCS-2le es muy, muy cerca de UTF-16: http://en.wikipedia.org/wiki/UTF-16/UCS-2 –

4

Intente abrir el archivo con una capa de IO especificado, por ejemplo, :

open OUTPUT, "<:encoding(UTF-8)", $file or die "Can't open $file: $!\n"; 

Consulte perldoc open para más información sobre esto.

7

La respuesta está en la documentación para open, que también le indica perluniintro. :)

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

, usted puede obtener una lista de los nombres de las codificaciones que su perl soportes:

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

Después de eso, le toca a usted para averiguar lo que es la codificación del archivo. Esta es la misma forma en que abriría cualquier archivo con una codificación diferente a la predeterminada, ya sea definida por Unicode o no.

Tenemos un capítulo en Effective Perl Programming que pasa a través de los detalles.

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 
Cuestiones relacionadas