更新一个unicode文件给我中文字符

我有一个“Application.config”文件,它是一个包含类似Unicode的文件(而不是ANSI或UTF8)

... <GENERAL> ... <FULLVERSION>18.0.13.227</FULLVERSION> </GENERAL> ... 

下面的脚本应该将其更改为18.1.00.012,并在32位Perl / OS上执行:

 my ($Company, $Config); $Company=$ENV{ProgramData}."\\Sage\\Accounts\\2012\\Application.config"; if( -f $Company) { $Config=''; if(open(APPCONF, "<".$Company)) { while(<APPCONF>) { $Config.=$_; } close(APPCONF); } if($Config=~s/(<.FULLVERSION>.).*?(<.\/.FULLVERSION>.)/\1\xfa\2/mi) { $Config=~s/\xfa/1\x008\x00\.\x000\x001\.\x000\x000\x00\.\x000\x001\x002\x00/mi; if(open(APPCONF, ">".$Company)) { binmode(APPCONF); print APPCONF $Config; close APPCONF; } } } 

发生什么(在64位Perl上)是“FULLVERSION”看起来不错,但是“/ FULLVERSION”已经完全破坏,看起来像中文。

谁能帮忙?

皮特

 use autodie qw(:all); use IO::File qw(); require File::BOM; my $Company = $ENV{ProgramData} . "\\Sage\\Accounts\\2012\\Application.config"; # File::Slurp apparently is buggy with PerlIO, no time to investigate. # Let's read/write files the normal way. my $Config = do { open my $appconf, '<:via(File::BOM)', $Company; join q(), $appconf->getlines; }; $Config =~ s| (?<= <FULLVERSION> ) .* (?= </FULLVERSION> ) |18.1.0.012|msx; { open my $appconf, '>:encoding(UTF-16LE):via(File::BOM)', $Company; $appconf->print($Config); } 

更好的是,不要用正则表达式来改变XML,而应该使用XML模块 。 他们也了解UTF-16。




hexdump Application.bad_2.config

 0000:0170 | 09 00 3C 00 46 00 55 00 4C 00 4C 00 56 00 45 00 | ..<.FULLVE 0000:0180 | 52 00 53 00 49 00 4F 00 4E 00 3E 00 31 00 38 00 | RSION>.1.8. 0000:0190 | 2E 00 30 00 31 2E 00 30 00 30 00 2E 00 30 00 31 | ..0.1..0.0...0.1 0000:01A0 | 00 32 00 3C 00 2F 00 46 00 55 00 4C 00 4C 00 56 | .2.<./.FULLV 0000:01B0 | 00 45 00 52 00 53 00 49 00 4F 00 4E 00 3E 00 0D | .ERSION>.. 0000:01C0 | 00 0A 00 09 00 3C 00 2F 00 47 00 45 00 4E 00 45 | .....<./.GENE 

注意到你插入了奇数个字节。 这将移动所有的字节,并使低字节变成高字节,反之亦然。 特别是,在0x0194的偏移处,你有31 2E 00而不是31 00 2E 00