2010-03-17 36 views
7

Tôi đang sử dụng osql để chạy một số tập lệnh sql dựa vào cơ sở dữ liệu và sau đó tôi cần xem xét tệp kết quả để kiểm tra xem có bất kỳ lỗi nào xảy ra không. Vấn đề là Perl dường như không thích thực tế là các tập tin kết quả là Unicode.Làm cách nào để mở một tệp Unicode bằng Perl?

Tôi đã viết một kịch bản thử nghiệm nhỏ để kiểm tra nó và đầu ra đi ra tất cả warbled:

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

Bất kỳ ý tưởng? Tôi đã thử giải mã bằng cách sử dụng decode_utf8 nhưng nó không có sự khác biệt. Tôi cũng đã cố gắng thiết lập mã hóa khi mở tệp.

Tôi nghĩ rằng vấn đề có thể là osql đặt tệp kết quả theo định dạng UTF-16, nhưng tôi không chắc chắn. Khi tôi mở tệp trong ô văn bản, nó chỉ cho tôi biết 'Unicode'.

Edit: Sử dụng perl v5.8.8 Edit: Hex bãi:

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

Đầu ra trông như thế nào? Bạn có thể cung cấp một hex + ascii dump của sự khởi đầu của tập tin? –

+0

Output trông giống như sau: ■ 1> 2> M s g 1 5 1 5 1, L e v đ l 1 6, S t t e 1 –

+0

Tôi sẽ sử dụng gì để cung cấp một hex + ascii bãi chứa của sự bắt đầu của tập tin? –

Trả lời

15

Tệp có thể ở định dạng UCS2-LE (hoặc 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...

Khi mở tập tin để đọc, bạn cần phải xác định mã hóa:

#!/usr/bin/perl 

use strict; use warnings; 

my ($infile) = @ARGV; 

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

Lưu ý rằng fffe lúc đầu là BOM.

+1

Đó là chính xác những gì tôi đang tìm kiếm khi yêu cầu bãi chứa. :) –

+0

Cảm ơn - đó thực sự là UTF-16. –

+1

UCS-2le rất, rất gần với UTF-16: http://en.wikipedia.org/wiki/UTF-16/UCS-2 –

4

Thử mở các tập tin với một lớp IO quy định, ví dụ :

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

Xem thêm perldoc open để biết thêm về điều này.

7

Câu trả lời nằm trong tài liệu cho open, cũng chỉ cho bạn perluniintro. :)

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

Bạn có thể có được một danh sách tên của các bảng mã mà perl của bạn hỗ trợ:

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

Sau đó, nó thuộc vào bạn để tìm ra những mã hóa tập tin là. Điều này cũng giống như cách bạn mở bất kỳ tệp nào có mã hóa khác với tệp mặc định, cho dù tệp đó có được định nghĩa bằng Unicode hay không.

Chúng tôi có một chương trong Effective Perl Programming thông qua các chi tiết.

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 
Các vấn đề liên quan