使用不同编码编码时,两个不同的字符串可以具有相同的字节序列吗?

时间:2012-07-20 01:26:04

标签: java encoding character-encoding hash

使用不同编码编码时,两个不同的字符串是否具有相同的字节序列? 即,当使用两种不同的编码进行编码时,下面的示例中的一些“字符串一”和“字符串二” (Cp1252和UTF-8只是例子)会导致测试通过吗?

import java.io.UnsupportedEncodingException;
import java.util.Arrays;

import org.junit.Assert;
import org.junit.Test;

public class EncodingTest {
    @Test
    public void test() throws UnsupportedEncodingException {
        final byte[] sequence1 = "string one".getBytes("Cp1252");
        final byte[] sequence2 = "string two".getBytes("UTF-8");
        Assert.assertTrue(Arrays.equals(sequence1, sequence2));
    }
}

我的代码中的一个错误哈希从具有JVM默认编码的String生成的字节序列,我需要验证当代码使用不同的字符串和不同的JVM文件编码运行时是否会导致哈希冲突(运行时可能会发生这种情况)例如Windows和Linux。)

由于编码是字节序列和字符之间的映射,我认为可能有一些字符串和编码通过了上述测试。但只是想知道是否有任何众所周知的例子或一些很好的理由说明为什么我不应该依赖哈希冲突而不发生。

由于

PS:这仅适用于JDK 1.6支持的编码,而不适用于某些编码的编码。

5 个答案:

答案 0 :(得分:2)

是。举一个简单的例子,编码为ISO-8859-1的字符串“¡”(倒置的感叹号)和编码为ISO-8859-2的字符串“Ą”(带有ogoned的大写字母A)都成为单字节序列A1(十六进制)。当使用将字符映射到单个字节的非常简单的编码时,这种事情或多或少地显而易见;否则他们不会是不同的编码。当涉及更复杂的编码方案时,肯定会发生这种情况。

答案 1 :(得分:1)

这是一个简单的方法:大多数代码页和UTF-8共享ASCII编码(0x00 = 0x7F)。如果您的文本是纯英文的,那么它很可能是ASCII - 无论声明的编码是什么,因为它主要使用普通的非重音字符。

答案 2 :(得分:1)

如果源字符串采用支持多字节字符的编码,并且目标编码是不支持多字节字符的编码,则可能会发生冲突,因为多字节字符需要映射到单字节字符集。

例如,如果输入字符串是用中文编写的,并且目标字符集是 US-ASCII ,那么很多中文字符肯定会映射到相同的US-ASCII表示。

答案 3 :(得分:1)

是的,至少对于不同长度的琴弦是可能的。

字符串"\u2020"(或"†")在UTF-16中编码为0x20,0x20。这也是"\x20\x20"(两个ASCII空格的字符串)以ASCII编码的原因。

当然,The Dagger并不经常出现在语言中[= ^ _ ^ =],但是一些标准的[非拉丁语]字母表可以生成映射到标准上的类似字节序列(非控制字符)ASCII编码..以及更多关于控制字符的限制放宽。

找到一个案例,其中两个相似的“现实”字符串(例如相同的长度和“敏感数据”)可以映射到具有不同编码的相同字节序列将会更有趣。

答案 4 :(得分:1)

这段代码应该最终产生一个例子:

    while(true){
        Random r = new Random();
        byte[] bytes = new byte[4];
        r.nextBytes(bytes);
        try{
            String raw = Arrays.toString(bytes);
            String utf8 = new String(bytes, "UTF-8");
            String latin1 = new String(bytes, "ISO-LATIN-1");
            System.out.println(raw + " is " + utf8 + " or " + latin1);
            break;
        }catch(Exception e){}
    }