解决错误:编码UTF8的不可映射字符

时间:2013-08-15 11:51:39

标签: java perl maven utf8-decode

我有一个maven项目,我父pom中的字符编码设置为UTF-8。

    <plugin>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>2.3.2</version>
      <configuration>
        <source>1.7</source>
        <target>1.7</target>
        <encoding>UTF-8</encoding>
      </configuration>
    </plugin>

但是在Java文件中,使用了` or之类的某些字符,这会导致编译错误。

在Eclipse(Properties ---- Resource ----- Text File encoding和Windows - preferences --- workspace --- text files encoding)中,我已将编码指定为UTF-8。请让我知道如何解决这个问题。

PERL CODE要做转换的事情

use strict;
use warnings;
use File::Find;
use open qw/:std :utf8/;

my $dir = "D:\\files";


find({ wanted => \&collectFiles}, "$dir");

sub collectFiles {
    my $filename = $_;
        if($filename =~ /.java$/){
        #print $filename."\n";
        startConversion($filename);
    }
}

sub startConversion{
    my $filename = $_;
    print $filename."\n";
    open(my $INFILE,  '<:encoding(cp1252)',  $filename) or die $!;
    open(my $OUTFILE, '>:encoding(UTF-8)', $filename) or die $!;
}

2 个答案:

答案 0 :(得分:1)

这两行不会启动或执行重新编码:

open(my $INFILE,  '<:encoding(cp1252)',  $filename) or die $!;
open(my $OUTFILE, '>:encoding(UTF-8)', $filename) or die $!;

打开文件>会截断它,删除内容。有关详细信息,请参阅open documentation

相反,您必须从第一个文件中读取数据(自动对其进行解码),然后将其写回另一个文件(自动对其进行编码)。因为源文件和目标文件在这里是相同的,并且由于Windows下文件处理的怪癖,我们应该将输出写入临时文件:

use autodie;  # automatic error handling :)

open my $in,  '<:encoding(cp1252)', $filename;
open my $out, '>:encoding(UTF-8)', "$filename~";  # or however you'd like to call the tempfile
print {$out} $_ while <$in>;  # copy the file, recoding it
close $_ for $in, $out;

rename "$filename~" => $filename;  # BEWARE: doesn't work across logival volumes!

如果文件足够小(提示:通常是源代码),那么你也可以将它们加载到内存中:

use File::Slurp;

my $contents = read_file $filename, { binmode => ':encoding(cp1252)' };
write_file $filename, { binmode => ':encoding(UTF-8)' }, $contents;

答案 1 :(得分:0)

如果您使用的是Linux或Mac OS X,则可以使用iconv将文件转换为UTF-8。 Java 1.7不允许使用非utf8字符,但Java 1.6不允许(尽管它会产生警告)。我知道,因为我的Mac上有Java 1.7,而我无法编译我们的一些代码,因为Windows用户和我们的Linux连续构建机器都可以,因为他们都使用Java 1.6。

Perl脚本的问题在于您打开了一个用于读取的文件和用于写入的相同文件,但您使用的是相同的文件名。当您打开文件进行写入时,您将删除其内容。

#! /usr/bin/env perl
use warnings;
use strict;
use feature qw(say);

use File::Find;

use strict;
use warnings;
use autodie;

use constant  {
    SOURCE_DIR       => 'src',
};


my @file_list;
find {
    next unless -f;
    next unless /\.java$/;
    push $file_list, $File::Find::name;
}, SOURCE_DIR;

for my $file ( @file_list ) {
    open my $file_fh, "<:encoding(cp1252)", $file;
    my @file_contents = <$file_fh>;
    close $file_fh;

    open my $file_fh, ">:encoding(utf8)", $file;
    print {$file_fh} @file_contents;
    close $file_fh;
}

注意我正在将整个文件读入内存,这应该可以使用Java源代码。即使是庞大的源文件(10,000行长,平均行长度为120个字符)也只会超过1.2兆字节。除非您使用的是TRS-80,否则我的1.2兆字节文件不应该是内存问题。如果您想严格要求,请使用File::Temp创建要写入的临时文件,然后使用File::Copy重命名该临时文件。两者都是标准的Perl模块。

您也可以将整个程序包含在find子程序中。