2010-03-17 11 views
7

Ich benutze osql, um mehrere SQL-Skripte gegen eine Datenbank laufen zu lassen, und dann muss ich in der Ergebnisdatei nachsehen, ob irgendwelche Fehler aufgetreten sind. Das Problem ist, dass Perl die Tatsache nicht zu mögen scheint, dass die Ergebnisdateien Unicode sind.Wie kann ich eine Unicode-Datei mit Perl öffnen?

schrieb ich ein kleines Testskript zu testen und die Ausgabe alle trällerte kommt heraus:

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

Irgendwelche Ideen? Ich habe versucht Decodierung mit decode_utf8, aber es macht keinen Unterschied. Ich habe auch versucht, die Kodierung beim Öffnen der Datei einzustellen.

Ich denke, das Problem könnte sein, dass osql die Ergebnisdatei im UTF-16-Format legt, aber ich bin mir nicht sicher. Wenn ich die Datei im Textpad öffne, sagt sie mir einfach 'Unicode'.

Edit: Mit Perl v5.8.8 Edit: Hex-Dump:

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

Wie sieht die Ausgabe aus? Können Sie einen hex + ascii-Dump am Anfang der Datei angeben? –

+0

Die Ausgabe sieht ungefähr so ​​aus: ■ 1> 2> M s g 1 5 1 5 1, L e v e l 1 6, S t a t e 1 –

+0

Was würde ich verwenden, um einen hex + ascii-Dump vom Anfang der Datei zu liefern? –

Antwort

15

Die Datei ist vermutlich in UCS2-LE (oder UTF-16 Format).

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...

Wenn eine solche Datei zum Lesen öffnen, müssen Sie die Codierung angeben:

#!/usr/bin/perl 

use strict; use warnings; 

my ($infile) = @ARGV; 

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

Beachten Sie, dass die fffe am Anfang der BOM ist.

+1

verfügt Das war genau das, wonach ich suchte, als ich nach der Müllkippe fragte. :) –

+0

Danke - es war eigentlich UTF-16. –

+1

UCS-2le ist sehr, sehr nah an UTF-16: http://en.wikipedia.org/wiki/UTF-16/UCS-2 –

4

Versuchen Sie die Datei mit einer IO-Schicht Öffnung angegeben, z.B. :

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

Weitere Informationen hierzu finden Sie unter perldoc open.

7

Die Antwort ist in der Dokumentation für open, die Sie auch auf perluniintro verweist. :)

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

Sie können eine Liste mit den Namen der Kodierungen, die Ihre perl unterstützt:

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

Danach ist es an Ihnen, um herauszufinden, was die Datei-Codierung ist. Dies ist die gleiche Art und Weise, in der Sie eine Datei öffnen, die eine andere Codierung als die Standardeinstellung aufweist, unabhängig davon, ob sie von Unicode definiert ist oder nicht.

Wir haben ein Kapitel in Effective Perl Programming, das durch die Details geht.

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 
Verwandte Themen