如何使用perl处理格式类似于unicode的文件?

Ori*_*pax 6 perl encode file

我有一个遗留程序,运行后,它将生成一个日志文件.现在我需要分析这个日志文件.

但文件格式很奇怪.请看下面的内容,我用vi打开它,它看起来像一个unicode文件,但它不是FFFE启动的.在我用记事本打开它之后,将它保存并再次打开,我发现记事本添加了FFFE.然后我可以使用命令'type log.txt> log1.txt"将整个文件转换为ANSI格式.稍后在perl中,我可以使用/ TDD/in perl来搜索我需要的内容.

但是现在,我无法处理这种文件格式.

任何评论或想法将非常感激.

0000000: 5400 4400 4400 3e00 2000 4c00 6f00 6100  T.D.D.>. .L.o.a.
Run Code Online (Sandbox Code Playgroud)

记事本保存后

0000000: fffe 5400 4400 4400 3e00 2000 4c00 6f00  ..T.D.D.>. .L.o.

open STDIN, "< log.txt";
while(<>)
{
  if (/TDD/)
  {
    # Add my logic.
  }
}
Run Code Online (Sandbox Code Playgroud)

我已经阅读了非常有用的线程,但仍然无法解决我的问题. 如何使用Perl打开Unicode文件?

我无法添加答案,所以我编辑了我的帖子.

谢谢迈克尔,我尝试了你的脚本,但得到了以下错误.我查了我的perl版本是5.1,OS是windows 2008.

* ascii
* ascii-ctrl
* iso-8859-1
* null
* utf-8-strict
* utf8
UTF-16:Unrecognised BOM 5400 at test.pl line 12.
Run Code Online (Sandbox Code Playgroud)

更新

我用命令尝试了UTF-16LE:

perl.exe open.pl utf-16le utf-16 <my log file>.txt
Run Code Online (Sandbox Code Playgroud)

但我仍然得到错误

UTF-16LE:Partial character at open.pl line 18, <$fh> line 1824.
Run Code Online (Sandbox Code Playgroud)

另外,我试过utf-16be,得到了同样的错误.

如果我使用utf-16,我会得到错误

UTF-16:Unrecognised BOM 5400 at open.pl line 18.
Run Code Online (Sandbox Code Playgroud)

open.pl第18行

is "print while <$fh>;"
Run Code Online (Sandbox Code Playgroud)

任何的想法?

更新时间:2011年5月11日.谢谢你们的帮助.我解决了这个问题.我发现日志文件中的数据毕竟不是UTF-16.所以,我必须通过visual studio编写一个.net项目.它将使用UTF-16读取日志文件并使用UTF-8写入新文件.然后我使用perl脚本来解析文件并生成结果数据.它现在有效.

所以,如果你们中的任何人都知道如何使用perl读取包含许多垃圾数据的文件,请告诉我,非常感谢.

例如垃圾数据样本

tests.cpp:34)
????????????????????????
Run Code Online (Sandbox Code Playgroud)

使用十六进制阅读器打开它:

0000070: a88d e590 80e4 9080 e490 80e3 b880 e280  ................
0000080: 80e4 b080 e6bc 80e6 8480 e690 80e6 a480  ................
0000090: e6b8 80e6 9c80 e280 80e6 8c80 e68c 80e6  ................
00000a0: b480 e68c 80e6 bc80 e788 80e6 9480 e2b8  ................
Run Code Online (Sandbox Code Playgroud)

Lum*_*umi 6

您的文件似乎以UTF-16LE编码.记事本添加的字节称为"字节顺序标记",或称为BOM.

以下是使用Perl读取文件的方法:

use strict;
use warnings;
use Encode;
# list loaded encodings
print STDERR map "* $_\n", Encode->encodings;
# read arguments
my $enc = shift || 'utf16';
die "no files :-(\n" unless @ARGV;
# process files
for ( @ARGV ) {
    open my $fh, "<:encoding($enc)", $_ or die "open $_: $!";
    print <$fh>;
    close $fh;
}
# loaded more encodings now
print STDERR map "* $_\n", Encode->encodings;
Run Code Online (Sandbox Code Playgroud)

继续这样做,注意为您的文件提供正确的编码:

perl open.pl utf16 open.utf16be.txt
perl open.pl utf16 open.utf16le.txt
perl open.pl utf16le open.utf16le.nobom.txt
Run Code Online (Sandbox Code Playgroud)

以下是tchrist建议的修订版:

use strict;
use warnings;
use Encode;

# read arguments
my $enc_in  = shift || die 'pass file encoding as first parameter';
my $enc_out = shift || die 'pass STDOUT encoding as second parameter';
print STDERR "going to read files as encoded in: $enc_in\n";
print STDERR "going to write to standard output in: $enc_out\n";
die "no files :-(\n" unless @ARGV;

binmode STDOUT, ":encoding($enc_out)"; # latin1, cp1252, utf8, UTF-8

print STDERR map "* $_\n", Encode->encodings; # list loaded encodings

for ( @ARGV ) { # process files
    open my $fh, "<:encoding($enc_in)", $_ or die "open $_: $!";
    print while <$fh>;
    close $fh;
}

print STDERR map "* $_\n", Encode->encodings; # more encodings now
Run Code Online (Sandbox Code Playgroud)