我正在将项目从 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 );
}
以下逻辑并不真正相关(?),因为在第一个系统输出之后前面提到的“?”打印而不是正确的字符(因此以下测试失败)。也没有使用默认平台编码。
测试根据TransformationMap.properties文件对每个字符进行转换,其形式如下(仅摘录):
Ý=Y
ý=y
Ž=Z
ž=z
°=.
€=EUR
需要注意的是,当我使用Ant构建项目时,测试运行没有任何问题。
我自己找到了“解决方案”:
我必须将编码传递到 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>
感谢您的所有回复和附加评论!
调试 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
强制完全重新编译。我遇到了此类真正有弹性的问题并设置环境变量
MAVEN_OPTS=-Dfile.encoding=UTF-8
为我解决了这个问题。
您的问题不是源文件的编码(因此也是类文件中的字符串),而是问题是
System.out
的隐式 PrintStream
的编码。它使用 file.encoding
表示系统编码,这在 Windows 中是 ANSI 代码页。
您必须使用 OEM 代码页设置
PrintWriter
(或者您使用专用于此目的的类:Console)。
另请参阅与此相关的各种错误:http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4153167
这对我有用:
...
<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>
以下工作对我来说没有任何问题:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<test>com.testsuite.JunitTestSuite</test>
*<argLine>${argLine} -Dfile.encoding=UTF-8</argLine>*
</configuration>
</plugin>