Domanda

EDIT:Sono stato convinto che questa domanda è un po ' non sensical.Grazie a chi ha risposto.Mi può postare una domanda che è più specifico.

Oggi mi stava investendo alcuni problemi di codifica e ha scritto questo test di unità per isolare una base repro caso:

int badCount = 0;
for (int i = 1; i < 255; i++) {
    String str = "Hi " + new String(new char[] { (char) i });

    String toLatin1  = new String(str.getBytes("UTF-8"), "latin1");
    assertEquals(str, new String(toLatin1.getBytes("latin1"), "UTF-8"));

    String toWin1252 = new String(str.getBytes("UTF-8"), "Windows-1252");
    String fromWin1252 = new String(toWin1252.getBytes("Windows-1252"), "UTF-8");

    if (!str.equals(fromWin1252)) {
        System.out.println("Can't encode: " + i + " - " + str + 
                           " - encodes as: " + fromWin1252);
        badCount++;
    }
}

System.out.println("Bad count: " + badCount);

L'output:

    Can't encode: 129 - Hi ? - encodes as: Hi ??
    Can't encode: 141 - Hi ? - encodes as: Hi ??
    Can't encode: 143 - Hi ? - encodes as: Hi ??
    Can't encode: 144 - Hi ? - encodes as: Hi ??
    Can't encode: 157 - Hi ? - encodes as: Hi ??
    Can't encode: 193 - Hi Á - encodes as: Hi ??
    Can't encode: 205 - Hi Í - encodes as: Hi ??
    Can't encode: 207 - Hi Ï - encodes as: Hi ??
    Can't encode: 208 - Hi ? - encodes as: Hi ??
    Can't encode: 221 - Hi ? - encodes as: Hi ??
    Bad count: 10

JDK 1.6.0_07 su Mac OS 10.6.2

La mia osservazione:

Latin1 simmetricamente codifica tutte le 254 caratteri.Windows-1252 non.I tre caratteri stampabili (193, 205, 207) sono gli stessi codici in Latin1 e Windows-1252, quindi non mi aspetto problemi.

Qualcuno può spiegare questo comportamento?È questo un JDK bug?

-- Giacomo

È stato utile?

Soluzione

A mio parere il programma di test è profondamente sbagliata, perché rende le trasformazioni in modo efficace inutili tra le stringhe senza alcun significato semantico.

Se si desidera verificare se tutti i valori di byte sono valori validi per un dato di codifica, quindi qualcosa di simile potrebbe essere più simile al primo:

public static void tryEncoding(final String encoding) throws UnsupportedEncodingException {
    int badCount = 0;
    for (int i = 1; i < 255; i++) {
        byte[] bytes = new byte[] { (byte) i };

        String toString = new String(bytes, encoding);
        byte[] fromString = toString.getBytes(encoding);

        if (!Arrays.equals(bytes, fromString)) {
            System.out.println("Can't encode: " + i + " - in: " + Arrays.toString(bytes) + "/ out: "
                    + Arrays.toString(fromString) + " - result: " + toString);
            badCount++;
        }
    }

    System.out.println("Bad count: " + badCount);
}

Si noti che gli ingressi test questo programma di test in base alle (usnigned) valori byte da 1 a 255. Il codice in questione utilizza valori char (equivalente a codepoints Unicode in questo intervallo) da 1 a 255.

Provare a stampare l'array di byte effettivo gestito dal programma nell'esempio e si vede che non sei in realtà controllando tutti i valori di byte e che alcune delle tue partite "cattivi" sono duplicati di altri.

L'esecuzione di questo con "Windows-1252" come argomento produce questo risultato:

Can't encode: 129 - in: [-127]/ out: [63] - result: �
Can't encode: 141 - in: [-115]/ out: [63] - result: �
Can't encode: 143 - in: [-113]/ out: [63] - result: �
Can't encode: 144 - in: [-112]/ out: [63] - result: �
Can't encode: 157 - in: [-99]/ out: [63] - result: �
Bad count: 5

Il che ci dice che Windows-1252 non accetta i valori del byte 129, 1441, 143, 144 e 157 come valori validi. . (Nota:. Sto parlando di valori di byte senza segno qui Il codice sopra mostra -127, -115, ... perché Java conosce solo byte unsigned)

L'articolo di Wikipedia su Windows-1252 sembra per verificare questa osservazione affermando questo :

  

Secondo le informazioni su Microsoft e di siti web del Consorzio Unicode, le posizioni 81, 8D, 8F, 90, e 9D sono inutilizzati

Altri suggerimenti

Che cosa il vostro codice (String->byte[]->String, due volte) è praticamente la di fronte di transcodifica, e non ha senso a tutti (è praticamente garantito per perdere i dati).Transcodifica significa byte[]->String->byte[]:

public byte[] transcode(byte[] input, String inputEnc, String targetEnc)
{
    return new String(input, inputEnc).getBytes(targetEnc);
}

E, naturalmente, non perde i dati quando l'input contiene caratteri che la codifica destinazione non supporta.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top