2017-11-29 6 views
0

私はバイト単位で特定のサイズに文字列を切り捨て、以下の方法で、持っている:この(おそらく)エンコード関連のエラー(Java、Gradle)を修正するにはどうすればよいですか?

public class Utils { 
    public static String trimStringToBytesSize(String s, int length) { 
     if (s == null || length < 0) return null; 
     int trimLength = Math.min(length, s.length()); 
     String trimmedString = s; 
     while (trimmedString.getBytes().length > length && trimLength >= 0) { 
      trimmedString = s.substring(0, trimLength); 
      trimLength--; 
     } 
     return trimmedString; 
    } 
} 

を、私はそれのためにいくつかのテストを書いた:

@Test 
public void trimStringToBytesSize() { 
[...] 
    trimStringToBytesSizeTestLogic("Шалом", 
      6, 
      "Шал" 
    ); 
[...] 
} 

private void trimStringToBytesSizeTestLogic(final String input, final int 
     stringLength, final String expectedResult) { 
    final String actRes = Utils.trimStringToBytesSize(input, stringLength); 
    Assert.assertEquals(expectedResult, actRes); 
} 

このテストでは、IntelliJのアイデア内部の細かい動作します。しかし、Gradleで実行すると失敗します。エラーは次のとおりです。

org.junit.ComparisonFailure: expected:<Шал[]> but was:<Шал[ом]> 

明らかに、それはバイトサイズと関係があります。

この方法とテストが含まれているminimal projectに問題を再現しようとしました。コードは同じですが、この最小限のプロジェクトでは元のコードに表示される問題は表示されません。

私はそれらの違いを見つけようとし、最小限のプロジェクトと元のプロジェクトのエンコードを比較しようとしました。 Notepad ++(UTF-8)によると同じです。

このテストに何が失敗する可能性がありますか?どうすれば修正できますか?

注:私はJava 1.8およびGradle 2.14を使用しています(お客様の要件により、最新のバージョンにアップグレードできません)。

答えて

2

文字列のバイトサイズは、文字列のバイトを生成するエンコーディングに大きく依存します。パラメータなしでString.getBytes()を使用すると、デフォルトのエンコーディングが使用されます。 * nixシステムではUTF-8、Windowsシステムでは「ISO-8859-1」です。

ШаломUTF-8の文字列は[-48, -88, -48, -80, -48, -69, -48, -66, -48, -68]です。
文字列ШаломISO-8859-1バイトは、ISO-8859-1に文字をエンコードすることができないため、?????という実質的には[63, 63, 63, 63, 63]です。

したがって、テストに成功すると、UTF-8がエンコードされます。失敗した場合は、エンコードにISO-8859-1があり、5バイトしかないため、文字列には触れません。

String getBytes()またはnew String()のようなメソッドを使用することはほとんどありません。明示的なエンコーディングを指定しないか、別のOSまたは異なるコンテキストで常に異なる動作をします。

関連する問題