2017-03-26 3 views
0

Ich verwende den folgenden Code, um einen String in einen Stream im Format UTF-8 zu schreiben. Ich setze die Bytes meiner Zeichenkette mit einem kurzen Vorzeichen voran, dann schreibe ich sie aus. Es gibt eine Ausnahme: Ich kann 0x0010 nicht voranstellen, weil es ein Schlüsselwort im endgültigen Format ist. Aber ich muss sicherstellen, dass der Leser mit genau der gleichen Zeichenfolge wie mein str Parameter endet, selbst wenn es die Länge 0x0010 ist.Gibt es irgendwelche Bytes, die UTF-8 nicht erkennt?

Gibt es Bytes (von 256), die UTF-8 am Ende der Zeichenfolge nicht erkennt?

Auch die folgende Frage hat mir nicht geholfen. Ich endete mit einem ? Zeichen am Ende. 30025693

+0

Ja, 0xFF ist eines der Bytes, die in UTF-8 nicht vorhanden sein können. Und alles ≥ 0xC0 kann nicht dauern. – user2233709

+0

'0xff' gibt'? 'Es funktioniert nicht. – Gergely

+1

Keine Ahnung, was du meinst. Ist Ihre Frage, welchen Wert Sie für DEAD_BYTE verwenden sollten? (Ich kenne Java nicht, keine Ahnung, ob dies ein sprachdefinierter Wert ist oder etwas, das Sie selbst definiert haben.) Wenn dem so ist, denke ich, dass es Ihnen mit 0x00 gut gehen würde. Wie auch immer, die Art, wie du mit dem speziellen Wert 0x10 umgehst, sieht für mich so falsch aus ... – user2233709

Antwort

1

Standardmäßig wird alles, was Sie in Ihre UTF-8-Zeichenfolge eingeben, als ein Zeichen dekodiert. Wenn es sich nicht um eine gültige UTF-8-Sequenz handelt, wird das Ersatzzeichen () verwendet - und erscheint weiterhin in Ihrer Ausgabe.

Sie können nur aus Ausgabezeichenfolge entfernen, aber es könnte auch aus Eingabezeichenfolge kommen. Stattdessen sollten Sie das zusätzliche Byte von UTF-8-Byte Streifen:

static String readString(final DataInputStream in) throws IOException { 
    int len = in.readUnsignedShort(); 
    final byte[] bytes = new byte[len]; 
    in.read(bytes); 
    if (bytes[len - 1] == -1) { 
     len--; 
    } 
    return new String(bytes, 0, len, UTF_8); 
} 

Eine weitere Option ist 0x0010 zu überspringen, wenn Länge codiert, und alle Werte oberhalb von 1 bewegen:

static void writeString(final DataOutputStream out, final String str) throws IOException { 
    final byte[] bytes = str.getBytes(UTF_8); 
    short len = (short) bytes.length; 
    if (bytes.length >= 0x0010) { 
     len++; 
    } 
    out.writeShort(len); 
    out.write(bytes); 
} 

static String readString(final DataInputStream in) throws IOException { 
    int len = in.readUnsignedShort(); 
    if (len == 0x0010) { 
     throw new IllegalStateException(); 
    } else if (len > 0x0010) { 
     len--; 
    } 
    final byte[] bytes = new byte[len]; 
    in.read(bytes); 
    return new String(bytes, UTF_8); 
} 

Diese beiden Lösungen Hacks sind und wird wahrscheinlich in der Zukunft Probleme verursachen. Die korrekte Lösung wäre, diese künstliche Beschränkung zu entfernen:

  1. Wenn Sie das endgültige Format steuern, ändern Sie es neu, so dass jede Byte-Sequenz zulässig ist.
  2. Andernfalls, wenn 0x0010 nur an erster Stelle nicht erlaubt ist, immer einen konstanten Wert eingeben, gefolgt von der tatsächlichen Länge. (Zum Beispiel: 00 11 00 10 ...)
  3. Andernfalls, wenn 0x0010 nicht an jeder Position erscheinen kann, entkommen sie: \x00\x10 als \\n codiert und \ codiert wird, als \\

Schließlich 0x0010 sieht aus wie UTF-16 codiert neue Zeile. Wenn das tatsächlich so ist, sollten Sie keine Binärdaten in den Text schreiben - das wird mehr Probleme verursachen. In diesem Fall sollten Sie Ihre Zeichenfolge direkt in diesen UTF-16-codierten Text einfügen oder eine ASCII-sichere Codierung wie base64 verwenden.

Verwandte Themen