代码之家  ›  专栏  ›  技术社区  ›  Jaco Pretorius

如何用Perl打开Unicode文件?

  •  10
  • Jaco Pretorius  · 技术社区  · 14 年前

    我正在使用OSQL对数据库运行几个SQL脚本,然后我需要查看结果文件以检查是否发生了任何错误。问题是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.
    
    4 回复  |  直到 7 年前
        1
  •  16
  •   Sinan Ünür    14 年前

    文件大概在 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 .

        2
  •  9
  •   brian d foy    11 年前

    答案在文档中 open ,这也向您指出 perluniintro . :)

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

    您可以得到一个编码的名称列表, perl 支持:

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

    在那之后,你就可以知道文件编码是什么了。这与打开任何编码与默认编码不同的文件的方式相同,不管它是否由Unicode定义。

    我们有一章 Effective Perl Programming 这就是细节。

        3
  •  5
  •   Eugene Yarmash    14 年前

    尝试打开指定了IO层的文件,例如:

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

    perldoc open 更多信息。

        4
  •  0
  •   Yordan Georgiev    7 年前
        #
        # -----------------------------------------------------------------------------
        # 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 ( $@ ) {
                $msg = $! . " " . $@ ;
                $ret = 1 ;
                $s = undef ;
             } else {
                $ret = 0 ; $msg = "ok for read file: $file" ;
             }
             return ( $ret , $msg , $s ) ;
        }
        #eof sub doReadFileReturnString