web-dev-qa-db-ja.com

Maven:UTF-8のソースエンコーディングが機能しませんか?

プロジェクトをAntからMavenに変換していますが、UTF-8文字を扱う特定のユニットテストで問題が発生しています。問題は、次の文字列に関するものです。

String l_string = "ČäÁÓý\n€řЖжЦ\n№ЯФКЛ";

問題は、ストリングが次のように読み取られるため、単体テストが失敗することです。

?äÁÓý
€????
?????

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を使用してプロジェクトをビルドすると、テストは問題なく実行されることに注意してください。

34
softandsafe

私は自分で「解決策」を見つけました。

エンコーディングを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>

すべての回答と追加のコメントをありがとう!

108
softandsafe
  1. Unicodeの問題をデバッグするときは、すべてをASCIIに変換するようにしてください。そうすれば、推測なしで文字列の内容を読み取って理解できます。つまり、StringEscapeUtils from commons-lang から_ä_を_\u00e4_に変換します。そうすれば、コンソールが印刷できないため、_?_が表示されます。 ""(_\u0020_)と ""(_\u00a0_)を区別できます

    テストケースでは、できるだけ早く入力のエスケープバージョンをチェックして、データが実際に期待したものであることを確認します。

    したがって、上記のコードは次のようになります。

    _assertEquals("\u010d\u00e4\u....", escape(l_string));
    _
  2. ファイルI/Oに正しいエンコーディングを使用していることを確認してください。 Javaのデフォルトエンコーディングを使用せず、常にInputStreamReader/OutputStreamWriterを使用し、使用するエンコーディングを指定します。

  3. POMは正しく見えます。 mvnを_-X_で実行して、正しいオプションを選択し、正しいオプションを使用してJavaコンパイラーを実行します。_mvn help:effective-pom_も役立つ場合があります。

  4. クラスファイルを逆アセンブルして、文字列を確認します。 Javaは_?_を使用して、何かを読み取れなかったことを示します。

    System.out.println( ">>> " + l_string );から_?_を取得する場合、これはコードがUTF-8でコンパイルされていないか、ソースファイルが別のUnicodeエンコーディング(UTF-16など)で保存されている可能性があることを意味します。

    問題の別の原因として、プロパティファイルが考えられます。 ISO-8859-1で保存されており、コンパイルプロセスによって変更されていないことを確認してください。

  5. Mavenが実際にファイルをコンパイルしていることを確認してください。 _mvn clean_を使用して、完全な再コンパイルを強制します。

9
Aaron Digulla

これは私のために働く:

...
 <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>
4
Eric Martinez

あなたの問題はソースファイルのエンコーディングではなく(したがってクラスファイル内の文字列)、問題はSystem.outの暗黙的なPrintStreamのエンコーディングです。システムエンコーディングを表すfile.encodingを使用します。これはWindowsではANSIコードページです。

OEMコードページでPrintWriterを設定する必要があります(または、このためのクラスを使用します: Console )。

以下のさまざまなバグも参照してください。 http://bugs.Java.com/bugdatabase/view_bug.do?bug_id=4153167

3
eckes

私はこの種の非常に回復力のある問題を抱えており、環境変数を設定していました

MAVEN_OPTS=-Dfile.encoding=UTF-8

私のために問題を修正しました。

0
David Vonka