【问题标题】:How can I open a Unicode file with Perl?如何使用 Perl 打开 Unicode 文件?
【发布时间】:2011-01-28 12:54:27
【问题描述】:

我正在使用 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.

【问题讨论】:

  • 输出是什么样的?你能提供文件开头的 hex+ascii 转储吗?
  • 输出如下所示: ■1 > 2 > M s g 1 5 1 5 1 , L e v e l 1 6 , S t a t e 1
  • 我将使用什么来提供文件开头的 hex+ascii 转储?
  • 如果您使用的是SQL 2005或更高版本,您可以考虑从OSQL切换到SQLCMD,其中有一个命令开关来控制输出文件的编码(-f)

标签: perl file unicode encoding


【解决方案1】:

文件大概是UCS2-LE(或UTF-16格式)。

C:\Temp> 记事本 test.txt

C:\Temp> xxd test.txt
0000000: fffe 5400 6800 6900 7300 2000 6900 7300 ..T.h.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': $!";

注意开头的fffeBOM

【讨论】:

  • 这正是我在要求转储时所寻找的。 :)
  • 谢谢 - 它实际上是 UTF-16。
【解决方案2】:

答案在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】:

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

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

    请参阅perldoc open 了解更多信息。

    【讨论】:

      【解决方案4】:
          #
          # -----------------------------------------------------------------------------
          # 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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-06-04
        • 2014-07-18
        • 2010-10-23
        • 2011-03-16
        • 2014-01-03
        • 2014-01-02
        • 2010-12-02
        • 1970-01-01
        相关资源
        最近更新 更多