Java 1.6 Windows-1252 codifica non riesce a 3 caratteri
-
23-09-2019 - |
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
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.