2010-03-17 62 views
7

我正在使用osql來針對數據庫運行多個sql腳本,然後我需要查看結果文件以檢查是否發生任何錯誤。問題是Perl似乎不喜歡結果文件是Unicode的事實。如何用Perl打開一個Unicode文件?

我寫了一個小的測試腳本來測試它和輸出自帶了所有啁啾:

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

任何想法?我試過使用decode_utf8進行解碼,但沒有區別。我也試着在打開文件時設置編碼。

我認爲問題可能是osql把結果文件放在UTF-16格式,但我不知道。當我在文本板中打開文件時,它只是告訴我'Unicode'。

編輯:使用perl v5.8.8 編輯:十六進制轉儲:

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

輸出是什麼樣的?你能提供一個hex + ascii轉儲文件的開頭嗎? – 2010-03-17 11:20:43

+0

輸出結果如下所示:■1> 2> M s g 1 5 1 5 1,L e v e l 6,S t a t e 1 – 2010-03-17 11:32:04

+0

我會用什麼來提供文件開頭的十六進制+ ASCII轉儲? – 2010-03-17 11:32:52

回答

15

該文件推測爲UCS2-LE(或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...

當閱讀打開這樣的文件,你需要指定編碼:

#!/usr/bin/perl 

use strict; use warnings; 

my ($infile) = @ARGV; 

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

注意,fffe開頭是BOM

+1

這正是我在尋求轉儲時所需要的。 :) – 2010-03-17 13:25:31

+0

謝謝 - 它實際上是UTF-16。 – 2010-03-17 14:45:04

+1

UCS-2le非常非常接近UTF-16:http://en.wikipedia.org/wiki/UTF-16/UCS-2 – 2010-03-17 15:53:43

4

嘗試打開與IO層中指定的文件,例如:

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

有關更多信息,請參閱perldoc open

7

答案在open的文檔中,該文檔也指向perluniintro。 :)

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

你可以得到你的perl支持編碼名稱的列表:

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

之後,它給你找出文件編碼是什麼。這與您使用不同於默認值的編碼打開任何文件的方式相同,不管它是否由Unicode定義。

我們在Effective Perl Programming中有一章介紹細節。

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