2011-11-04 7 views
5

Ricevo da presa una stringa in un array di byte che assomigliano:Come rilevare la fine della stringa nella serie di byte nella conversione di stringhe?

[128,5,6,3,45,0,0,0,0,0] 

La dimensione proposta dal protocollo di rete è la lunghezza totale della stringa (compresi zeri) così, nel mio exemple 10.

Se io semplicemente:

String myString = new String(myBuffer); 

ho alla fine della stringa 5 non corretto caracter. La conversione non sembra rilevare la fine del carattere di stringa (0).

Per ottenere la dimensione corretta e la stringa corretta faccio questo:

int sizeLabelTmp = 0; 
//Iterate over the 10 bit to get the real size of the string 
for(int j = 0; j<(sizeLabel); j++) { 
    byte charac = datasRec[j]; 
    if(charac == 0) 
     break; 
    sizeLabelTmp ++; 
} 
// Create a temp byte array to make a correct conversion 
byte[] label = new byte[sizeLabelTmp]; 
for(int j = 0; j<(sizeLabelTmp); j++) { 
    label[j] = datasRec[j]; 
} 
String myString = new String(label); 

C'è un modo migliore per gestire il problema?

Grazie

risposta

7

0 non è un "carattere di fine stringa". È solo un byte. Il fatto che arrivi o meno solo alla fine della stringa dipende da quale codifica stai usando (e da cosa può essere il testo). Ad esempio, se si utilizza UTF-16, ogni altro byte sarà 0 per i caratteri ASCII.

Se siete sicuri che il primo 0 indica la fine della stringa, è possibile utilizzare qualcosa come il codice che hai dato, ma mi piacerebbe riscriverlo come:

int size = 0; 
while (size < data.length) 
{ 
    if (data[size] == 0) 
    { 
     break; 
    } 
    size++; 
} 

// Specify the appropriate encoding as the last argument 
String myString = new String(data, 0, size, "UTF-8"); 

I fortemente consiglia di non utilizzare solo la codifica predefinita della piattaforma: non è portabile e potrebbe non consentire tutti i caratteri Unicode. Tuttavia, non puoi decidere solo arbitrariamente: devi assicurarti che tutto ciò che produce e consuma questi dati sia d'accordo sulla codifica.

Se si ha il controllo del protocollo, sarebbe molto meglio se si potesse introdurre un prefisso di lunghezza prima della stringa, per indicare quanti byte sono nella forma codificata. In questo modo sarai in grado di leggere esattamente la giusta quantità di dati (senza "sovrascrittura") e sarai in grado di dire se i dati sono stati troncati per qualche motivo.

+0

+1 per prendere in considerazione la codifica. Se la roba ricevuta tramite socket è solo una stringa Java serializzata, dovrebbe essere ok. –

+0

@G_H: "Solo una stringa Java serializzata" non specifica realmente il formato di serializzazione. Se l'OP usasse la serializzazione binaria Java, non avrebbe comunque eseguito questa operazione in modo esplicito ... e se si tratta di un altro formato di serializzazione, dovremmo sapere * quale *. –

+0

Probabilmente dovrei smettere di parlare ... Il fatto è che sono sempre stato lontano dalla serializzazione e non conosco bene i dettagli. Solitamente JAXB o JPA sono l'unica cosa che considero un'opzione. –

2

Le stringhe in Java non terminano con uno 0, come in alcune altre lingue. 0 diventerà il cosiddetto carattere null, che può apparire in una stringa. Vi suggerisco di utilizzare uno schema di ritaglio che rileva il primo indice dell'array che è uno 0 e utilizza un sub-array per costruire la stringa (supponendo che tutto il resto sarà 0 dopo), o semplicemente costruire la stringa e chiamare trim(). Questo rimuoverà lo spazio bianco iniziale e finale, che è qualsiasi carattere con codice ASCII 32 o inferiore.

Quest'ultimo non funzionerà se si hanno spazi bianchi iniziali da conservare. Usare un oggetto StringBuilder ed eliminare caratteri alla fine, a patto che siano il carattere null, funzionerebbe meglio in quel caso.

2

È sempre possibile iniziare alla fine della serie di byte e andare indietro finché non si preme il primo non zero. Quindi copialo in un nuovo byte e poi lo stringa. Spero che questo aiuti:

byte[] foo = {28,6,3,45,0,0,0,0}; 
    int i = foo.length - 1; 

    while (foo[i] == 0) 
    { 
     i--; 
    } 

    byte[] bar = Arrays.copyOf(foo, i+1); 

    String myString = new String(bar, "UTF-8"); 
    System.out.println(myString.length()); 

Vi darà un risultato di 4.

1

Mi sembra che si stia ignorando il conteggio di lettura restituito dal metodo read(). Probabilmente i byte null finali non venivano inviati, probabilmente sono ancora lasciati dallo stato iniziale del buffer.

int count = in.read(buffer); 
if (count < 0) 
    ; // EOS: close the socket etc 
else 
    String s = new String(buffer, 0, count); 
+0

Il buffer mostrato nel mio OP è solo un estratto di un intero pacchetto. La stringa viene inviata nel mezzo di molti altri dati. – grunk

+0

@grunk quindi il protocollo deve dirvi quanta parte di essa è la stringa, sia con la terminazione nulla che con un prefisso di lunghezza. – EJP

9

Potrebbe essere troppo tardi, ma può aiutare gli altri. La cosa più semplice che puoi fare è new String(myBuffer).trim() che ti dà esattamente quello che vuoi.

1

Non immergersi nelle considerazioni sul protocollo che l'OP originale ha menzionato, che ne dici di questo per tagliare gli zeri finali?

public static String bytesToString(byte[] data) { 
    String dataOut = ""; 
    for (int i = 0; i < data.length; i++) { 
     if (data[i] != 0x00) 
      dataOut += (char)data[i]; 
    } 
    return dataOut; 
} 
Problemi correlati