[英]Solving error: unmappable character for encoding UTF8
我有一个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中(属性----资源-----文本文件编码和Windows--preferences --- workspace ---文本文件编码),我将编码指定为UTF-8。 请让我知道如何解决此问题。
执行转换工作的PERL代码
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 $!;
}
这两行不开始也不执行重新编码:
open(my $INFILE, '<:encoding(cp1252)', $filename) or die $!;
open(my $OUTFILE, '>:encoding(UTF-8)', $filename) or die $!;
使用>
打开文件将其截断,这将删除内容。 有关更多详细信息,请参见open
文档 。
相反,您必须从第一个文件中读取数据(该文件自动解码),然后将其写回到另一个文件中(该文件自动编码)。 由于此处的源文件和目标文件是相同的,并且由于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;
如果您使用的是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 MB的文件应该不是内存问题。 如果要严格执行此操作,请使用File::Temp
创建要写入的临时文件,然后使用File::Copy
重命名该临时文件。 两者都是标准的Perl模块。
您也可以将整个程序包含在find
子例程中。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.