我正在将一个项目从Ant转换为Maven,我遇到了一个处理UTF-8字符的特定单元测试的问题。问题是关于以下字符串:
String l_string = "ČäÁÓý\n€řЖжЦ\n№ЯФКЛ";
问题是单元测试失败,因为String被读取如下:
?äÁÓý
€????
?????
java类保存为UTF-8,我还在pom.xml中指定了UTF-8的构建编码。
以下是 pom.xml 的摘录:
...
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.15</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-report-plugin</artifactId>
<version>2.15</version>
</plugin>
</plugins>
</build>
我在这里遗漏了什么吗?如果有人能帮助我,那就太好了。
更新
关于测试代码:
@Test
public void testTransformation()
{
String l_string = "ČäÁÓý\n€řЖжЦ\n№ЯФКЛ";
System.out.println( ">>> " + l_string );
c_log.info( l_string );
StringBuffer l_stringBuffer = new StringBuffer();
int l_stringLength = l_string.length();
String l_fileName = System.getProperty( "user.dir" ) + File.separator + "transformation" + File.separator + "TransformationMap.properties";
Transformation.init( l_fileName );
Properties l_props = Transformation.getProps();
for ( int i = 0; i < l_stringLength; i++ )
{
char l_char = l_string.charAt( i );
int l_intValue = (int) l_char;
if ( l_intValue <= 255 )
{
l_stringBuffer.append( l_char );
}
else
{
l_stringBuffer.append( l_props.getProperty( String.valueOf( l_char ), "" ) );
}
}
c_log.info( l_stringBuffer.toString() );
byte[] l_bytes = l_string.getBytes();
byte[] l_transformedBytes = Transformation.transform( l_bytes );
assertNotNull( l_transformedBytes );
}
以下逻辑并不真正相关(?)因为在第一个sysout之前提到“?”打印而不是正确的字符(因此以下测试失败)。也没有使用默认平台编码。
测试根据TransformationMap.properties文件转换每个字符,该文件采用以下格式(仅作摘录):
Ý=Y
ý=y
Ž=Z
ž=z
°=.
€=EUR
应该注意的是,当我使用Ant构建项目时,测试运行没有任何问题。
答案 0 :(得分:105)
我自己找到了一个“解决方案”:
我必须将编码传递给maven-surefire-plugin,但通常是
<encoding>${project.build.sourceEncoding}</encoding>
没用。我仍然不知道为什么,但是当我将命令行参数传递给插件时,测试按原样运行:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.15</version>
<configuration>
<argLine>-Dfile.encoding=UTF-8</argLine>
</configuration>
</plugin>
感谢您的所有回复和其他评论!
答案 1 :(得分:10)
调试Unicode问题时,请确保将所有内容转换为ASCII,这样您就可以阅读并理解字符串内部的内容,而无需猜测。这意味着您应该使用commons-lang3中的StringEscapeUtils
将ä
转换为\u00e4
。这样,您可以确定看到?
,因为控制台无法打印它。你可以区分“”(\u0020
)和“”(\u00a0
)
在测试用例中,请尽早检查输入的转义版本,以确保数据实际上符合您的预期。
所以上面的代码应该是:
assertEquals("\u010d\u00e4\u....", escape(l_string));
确保对文件I / O使用正确的编码。切勿使用Java的默认编码,请始终使用InputStreamReader
/ OutputStreamWriter
并指定要使用的编码。
POM看起来很正确。使用mvn
运行-X
以确保它选择正确的选项并使用正确的选项运行Java编译器。 mvn help:effective-pom
也可以提供帮助。
反汇编类文件以检查字符串。 Java将使用?
来表示它无法读取内容。
如果从?
获得System.out.println( ">>> " + l_string );
,则表示代码未使用UTF-8编译,或者源文件可能使用其他Unicode编码保存(UTF-16或类似)
另一个问题来源可能是属性文件。确保它已使用ISO-8859-1保存,并且未被编译过程修改。
确保Maven实际编译您的文件。使用mvn clean
强制进行完全重新编译。
答案 2 :(得分:4)
这对我有用:
...
<properties>
**<project.build.sourceEncoding>ISO-8859-1</project.build.sourceEncoding>
<project.reporting.outputEncoding>ISO-8859-1</project.reporting.outputEncoding>**
</properties>
...
<build>
<finalName>Project</finalName>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
**<encoding>${project.build.sourceEncoding}</encoding>**
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.2</version>
<configuration>
<warSourceDirectory>WebContent</warSourceDirectory>
</configuration>
</plugin>
</plugins>
</build>
答案 3 :(得分:3)
您的问题不是源文件的编码(因此也不是您的类文件中的String),但问题是System.out
隐含PrintStream
的编码。它使用代表系统编码的file.encoding
,这在Windows中是ANSI代码页。
您必须使用OEM代码页设置PrintWriter
(或者使用专门用于此目的的类:Console)。
另请参阅:http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4153167
中的各种错误答案 4 :(得分:0)
我有一个非常有弹性的问题并设置环境变量
library(ggplot2)
ggplot(dcast(DT, ... ~ measure),
aes(strain, avg, ymin = avg - SEM, ymax = avg + SEM, fill = dataset)) +
geom_col(position = "dodge") +
geom_errorbar(width=.1, position = position_dodge(width=0.9)) +
scale_fill_manual(values=c("lightseagreen", "indianred1")) +
theme_bw() +
labs(fill = "", y = "Average", x = "") +
facet_wrap(~ variable, scales = "free_y") +
theme(axis.text.x = element_text(angle = 65, hjust = 1))
为我解决了这个问题。