如何(大概)修复与编码有关的误差(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 Idea内部运行良好。但是,当我在gradle运行它时,它会失败。错误是:

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

显然,它与字节大小有关。

我试图在最小项目中重现问题,其中包含该方法和测试。该代码是相同的,但是在此最小项目中没有出现在原始代码中的问题。

我试图找出它们之间的区别,并比较了最小和原始项目中的编码。根据记事本 (UTF-8)。

是相同的。

还有什么可能导致该测试失败?我该如何修复?

注意:我正在使用Java 1.8和Gradle 2.14(由于客户的要求,我无法升级到最新版本)。

您是对的,字符串的字节大小在很大程度上取决于您使用字符串中的生成字节的编码。当您使用无参数的String.getBytes()时,使用默认编码。这是 *NIX系统上的UTF-8,Windows Systems上的" ISO-8859-1"。

UTF-8字节中的字符串Шалом[-48, -88, -48, -80, -48, -69, -48, -66, -48, -68]
ISO-8859-1字节中的字符串Шалом[63, 63, 63, 63, 63],它有效为?????,因为您的字符不能在ISO-8859-1中编码。

因此,当您的测试成功时,您将UTF-8作为编码,如果失败了,则将ISO-8859-1作为编码,仅有5个字节,因此不触摸字符串。

您几乎不应该在不指定明确编码的情况下使用String getBytes()new String()等方法,否则在不同的OS或不同上下文中始终具有不同的行为。

相关内容

  • 没有找到相关文章

最新更新