2011-05-06 92 views
6

我有一个传统程序,运行后它会生成一个日志文件。现在我需要分析这个日志文件。如何使用perl处理格式与unicode相似的文件?

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

任何意见或想法将非常赞赏。

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

记事本后,请保存它

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

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

我已阅读线程,这是非常有用的,但仍然不能解决我的问题。 How can I open a Unicode file with Perl?

我无法添加答案,所以我编辑我的线程。

谢谢迈克尔, 我试过你的脚本,但得到以下错误。我检查了我的perl版本是5.1,操作系统是Windows 2008

* ascii 
* ascii-ctrl 
* iso-8859-1 
* null 
* utf-8-strict 
* utf8 
UTF-16:Unrecognised BOM 5400 at test.pl line 12. 

更新

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

perl.exe open.pl utf-16le utf-16 <my log file>.txt 

,但我仍然得到了错误像

UTF-16LE:Partial character at open.pl line 18, <$fh> line 1824. 

另外,我试过utf-16be,得到了相同的e RROR。

如果我用UTF-16,我得到了错误

UTF-16:Unrecognised BOM 5400 at open.pl line 18. 

open.pl线18

is "print while <$fh>;" 

任何想法?

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

因此,如果你们中的任何人知道如何使用perl读取含有许多垃圾数据的文件,请告诉我,非常感谢。

例如垃圾数据样本

tests.cpp:34) 
਍吀䐀䐀㸀 䰀漀愀搀椀渀最 挀挀洀挀漀爀攀⸀搀氀 

使用十六进制读者打开它:

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 ................ 
+0

这可能有一些帮助:http://www.perlmonks.org/?node_id=615796 – 2011-05-06 07:32:07

+0

您是否尝试过为流读取指定不同的编码? – 2011-05-06 07:32:41

+0

您连接的问题的接受答案告诉您您需要做什么才能阅读您的UCS-2LE编码文件。我只是试了一下,它为我工作。 - 更具体地说明你“无法解决”的原因。 – daxim 2011-05-06 07:45:28

回答

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; 

这样进行,同时注意提供正确的编码文件:

perl open.pl utf16 open.utf16be.txt 
perl open.pl utf16 open.utf16le.txt 
perl open.pl utf16le open.utf16le.nobom.txt 

这里的修订版以下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 
+0

谢谢迈克尔。我试过,但得到了错误,如 'UTF-16:无法识别BOM 5400在test.pl行12'。 'print <$fh>;' – Orionpax 2011-05-06 08:03:24

+1

@Orionpax上的行,在Perl中,'utf16'编码需要BOM,因为它可以是大的或小的。请尝试使用“UTF-16LE”。 – cjm 2011-05-06 09:29:57

+0

然后你在没有BOM的文件上运行它。去更新我的例子。 – Lumi 2011-05-06 09:40:40