2014-09-19 7 views
8
byte[] byteArray = Charset.forName("UTF-8").encode("hello world").array(); 
System.out.println(byteArray.length); 

Perché la riga di codice sopra riportata è 12, non dovrebbe invece stamparne 11?Qual è la lunghezza di una stringa codificata in un ByteBuffer

+0

Ho il sospetto che la rete da questo è di non utilizzare il metodo ByteBuffer.array senza prima con attenzione leggendo la documentazione –

+0

Sono abbastanza sorpreso che tu abbia un accesso pubblico al backing array, piuttosto che essere costretto a usare i metodi get e put. – azurefrog

risposta

11

La lunghezza della matrice è la dimensione del ByteBuffer ' s capacità, che è generata da, ma non è uguale al numero di caratteri che stai codificando. Diamo uno sguardo a come ci allocare memoria per un ByteBuffer ...

Se si punta al metodo encode(), vi accorgerete che CharsetEncoder#encode(CharBuffer) assomiglia a questo:

public final ByteBuffer encode(CharBuffer in) 
    throws CharacterCodingException 
{ 
    int n = (int)(in.remaining() * averageBytesPerChar()); 
    ByteBuffer out = ByteBuffer.allocate(n); 
    ... 

Secondo il mio debugger, il averageBytesPerChar di un UTF_8$Encoder è 1.1 e l'input String ha 11 caratteri. 11 * 1.1 = 12.1, e il codice getta il totale a un int quando lo fa il calcolo, quindi la dimensione risultante del ByteBuffer è 12.

+5

Wow, mi chiedo chi sia la media e quale set di dati hanno usato.In qualche modo, mi ricorda la battuta sullo statistico che infila la testa nel forno e con i piedi nel congelatore e si dichiara, in media, comodamente caldo. –

1

Perché restituisce un ByteBuffer. Questa è la capacità del buffer (non proprio quella a causa della possibile divisione), non quanti byte vengono utilizzati. È un po 'come se malloc(10) è libero di restituire 32 byte di memoria.

System.out.println(Charset.forName("UTF-8").encode("hello world").limit()); 

Questo è 11 (come previsto).

+0

Io non la penso così. Se hai creato un array vuoto, sarebbe stato impostato su un valore predefinito e avrebbe potuto essere superiore al numero di byte utilizzati dopo l'assegnazione, ma in questo caso verrà invocato il costruttore di copia e mi aspetto che l'array sia inizializzato su il numero di caratteri passati. – ventsyv

+0

Quando si crea un array, '.length' sarà la lunghezza richiesta (cioè nelle specifiche Java). In questo caso, 'encode()' non dice cosa farà, solo che restituisce un 'ByteBuffer' con i caratteri codificati che hai richiesto. Altri lo hanno scavato ed è un dettaglio di implementazione, quindi questo comportamento sarà diverso anche tra le versioni di JVM e le implementazioni. –

+0

OK, questo ha senso. – ventsyv

0
import java.nio.charset.*; 
public class ByteArrayTest { 
    public static void main(String[] args) { 
     String theString = "hello world"; 
     System.out.println(theString.length()); 
     byte[] byteArray = Charset.forName("UTF-8").encode(theString).array(); 
     System.out.println(byteArray.length); 
     for (int i = 0; i < byteArray.length; i++) { 
      System.out.println("Byte " + i + " = " + byteArray[i]); 
     } 
    } 
} 

Risultati:

C:\JavaTools>java ByteArrayTest 
11 
12 
Byte 0 = 104 
Byte 1 = 101 
Byte 2 = 108 
Byte 3 = 108 
Byte 4 = 111 
Byte 5 = 32 
Byte 6 = 119 
Byte 7 = 111 
Byte 8 = 114 
Byte 9 = 108 
Byte 10 = 100 
Byte 11 = 0 

L'array è terminazione Null, come ogni buon C-stringa sarebbe.

(Ma a quanto pare la vera causa è il metodo traballante array. Probabilmente non deve essere usato in codice "produzione", se non con grande cura.)

+3

Non penso che il trailing 0 byte sia un terminatore nullo tanto quanto lo spazio buffer inutilizzato – Andreas

+0

@Andreas - Sì, probabilmente hai ragione - [array] (http://docs.oracle.com/javase/7 /docs/api/java/nio/ByteBuffer.html#array%28%29) è un'operazione semi-fasulla che restituisce il buffer interno di ByteBuffer e quindi non si sa quanto sarà grande. –

+0

@Andreas: il runtime Java è (immagino) implementato in C, quindi potrebbe essere stato conveniente per le stringhe essere surrettiziamente terminate con null. :-) –

Problemi correlati