3

異なるエンコーディングでエンコードされた2つの異なる文字列は、同じバイトシーケンスを持つことができますか?つまり、以下の例の「文字列1」と「文字列2」は、2つの異なるエンコーディング(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のデフォルトのエンコーディングで文字列から生成されたバイトシーケンスをハッシュし、コードが異なる文字列と異なるJVMファイルエンコーディングで実行されたときにハッシュ衝突が発生するかどうかを確認する必要があります(WindowsとLinuxで実行された場合に発生する可能性があります)例えば)。

エンコーディングはバイトシーケンスと文字の間のマッピングであるため、上記のテストに合格する文字列とエンコーディングがいくつかあると思います。しかし、よく知られている例があるかどうか、またはハッシュ衝突が発生しないことに依存すべきではない理由について知りたかっただけです。

ありがとう

PS:これは、JDK 1.6でサポートされているエンコーディング専用であり、一部の構成されたエンコーディングではサポートされていません。

4

5 に答える 5

2

はい。簡単な例を挙げると、ISO-8859-1としてエンコードされた文字列「¡」(逆感嘆符)とISO-8859-2としてエンコードされた文字列「Ą」(大文字のA)は、どちらもシングルバイトシーケンスになります。 A1(16進数)。文字を1バイトにマップする非常に単純なエンコーディングを使用すると、このようなことが起こることは多かれ少なかれ明らかです。そうでなければ、それらは異なるエンコーディングではありません。より複雑なエンコーディングスキームが関係している場合にも、それは確かに起こり得ます。

于 2012-07-20T04:47:11.490 に答える
1

これは簡単な方法です。ほとんどのコードページとUTF-8はASCIIエンコーディング(0x00 = 0x7F)を共有しています。テキストが平易な英語である場合、ASCIIである可能性が高くなります。宣言されたエンコーディングが何であれ、ほとんどの場合、平易でアクセントのない文字が使用されるためです。

于 2012-07-20T01:40:28.763 に答える
1

ソース文字列がマルチバイト文字をサポートするエンコーディングであり、ターゲットエンコーディングがマルチバイト文字をサポートしないエンコーディングである場合、マルチバイト文字は単一へのマッピングを必要とするため、衝突が発生する可能性があります。バイト文字セット。

たとえば、入力文字列が中国語で書かれていて、ターゲット文字セットがUS-ASCIIである場合、多くの漢字は確かに同じUS-ASCII表現にマップされます。

于 2012-07-20T01:43:14.487 に答える
1

はい、少なくとも長さの異なる文字列では可能です。

文字列"\u2020"(または"†")は0x20,0x20UTF-16のようにエンコードされます。これは、"\x20\x20"(2つのASCIIスペースの文字列)がASCIIでエンコードされるものでもあります。

もちろん、The Daggerは、言語で頻繁に登場することはありません[= ^ _ ^ =]が、一部の標準[非ラテン]アルファベットは、標準(非制御文字)ASCIIにマップする同様のバイトシーケンスを生成する可能性があります制御文字に関する制限が緩和された場合は、エンコーディング..およびその他多数。

2つの類似した「現実的な」文字列(たとえば、同じ長さと「適切なデータ」)が異なるエンコーディングで同じバイトシーケンスにマップできるケースを見つけることは、より興味深いでしょう。

于 2012-07-20T02:10:44.987 に答える
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){}
    }
于 2012-07-20T02:13:01.447 に答える