UTF-8 byte [] su String


243

Supponiamo che io abbia appena usato a BufferedInputStreamper leggere i byte di un file di testo codificato UTF-8 in un array di byte. So che posso usare la seguente routine per convertire i byte in una stringa, ma c'è un modo più efficiente / più intelligente di farlo che non solo iterare i byte e convertirli?

public String openFileToString(byte[] _bytes)
{
    String file_string = "";

    for(int i = 0; i < _bytes.length; i++)
    {
        file_string += (char)_bytes[i];
    }

    return file_string;    
}

17
Perché non puoi farlo String fileString = new String(_bytes,"UTF-8");?
CoolBeans,

1
In alternativa, è possibile utilizzare BufferedReader per leggere in un array di caratteri.
Andy Thomas,


@CoolBeans avrei potuto se avessi saputo farlo;) Grazie.
skeryl,

A seconda della dimensione del file, non sono sicuro caricare l'intero byte[]in memoria e convertirlo tramite new String(_bytes,"UTF-8")(o anche con blocchi con +=sulla stringa) è il più efficiente. Concatenare InputStreams e Reader potrebbe funzionare meglio, specialmente su file di grandi dimensioni.
Bruno,

Risposte:


498

Guarda il costruttore di String

String str = new String(bytes, StandardCharsets.UTF_8);

E se ti senti pigro, puoi usare la libreria IO di Apache Commons per convertire direttamente InputStream in una stringa:

String str = IOUtils.toString(inputStream, StandardCharsets.UTF_8);

13
O Guava's Charsets.UTF_8 se sei su JDK più vecchio di 1.7
siledh

6
Usa Guava's Charsets.UTF_8 se utilizzi l'API Android anche al di sotto dei 19 anni
Ben Clayton,

E se lo stile di controllo dice: "Istantanea illegale: Istantanea di java.lang.String dovrebbe essere evitata", allora cosa?
Attila Neparáczki,

1
Puoi vedere qui nella java.nio.charset.Charset.availableCharsets()mappa tutti i set di caratteri non solo i set di caratteri nel file StandardCharsets. E se vuoi usare qualche altro set di caratteri e vuoi comunque impedire al costruttore di String di UnsupportedEncodingExceptionjava.nio.charset.Charset.forName()
lanciarti

2
IOUtils.toString (inputStream, StandardCharsets.UTF_8) ora è obsoleto.
Aung Myat Hein,

41

La classe String di Java ha un costruttore incorporato per convertire l'array di byte in stringa.

byte[] byteArray = new byte[] {87, 79, 87, 46, 46, 46};

String value = new String(byteArray, "UTF-8");

9

Per convertire i dati utf-8, non puoi assumere una corrispondenza 1-1 tra byte e caratteri. Prova questo:

String file_string = new String(bytes, "UTF-8");

(Bah. Vedo che sono in grado di rallentare premendo il pulsante Pubblica la tua risposta.)

Per leggere un intero file come stringa, fai qualcosa del genere:

public String openFileToString(String fileName) throws IOException
{
    InputStream is = new BufferedInputStream(new FileInputStream(fileName));

    try {
        InputStreamReader rdr = new InputStreamReader(is, "UTF-8");
        StringBuilder contents = new StringBuilder();
        char[] buff = new char[4096];
        int len = rdr.read(buff);
        while (len >= 0) {
            contents.append(buff, 0, len);
        }
        return buff.toString();
    } finally {
        try {
            is.close();
        } catch (Exception e) {
            // log error in closing the file
        }
    }
}

4

Puoi usare il String(byte[] bytes) costruttore per questo. Vedi questo link per i dettagli. EDIT Devi anche considerare il set di caratteri predefinito del tuo plateform secondo il documento java:

Costruisce una nuova stringa decodificando l'array di byte specificato utilizzando il set di caratteri predefinito della piattaforma. La lunghezza della nuova stringa è una funzione del set di caratteri e quindi potrebbe non essere uguale alla lunghezza della matrice di byte. Il comportamento di questo costruttore quando i byte indicati non sono validi nel set di caratteri predefinito non è specificato. La classe CharsetDecoder deve essere utilizzata quando è richiesto un maggiore controllo sul processo di decodifica.


1
E se i byte non si trovano nel set di caratteri predefinito della piattaforma, è possibile utilizzare la versione con il secondo Charsetargomento per assicurarsi che la conversione sia corretta.
Mike Daniels,

1
@MikeDaniels In effetti, non volevo includere tutti i dettagli. Ho appena modificato la mia risposta
GETah


2

Sapendo che hai a che fare con una matrice di byte UTF-8, ti consigliamo di utilizzare il costruttore String che accetta un nome di set di caratteri . Altrimenti potresti lasciarti aperto ad alcune vulnerabilità di sicurezza basate sulla codifica dei set di caratteri. Nota che genera ciò UnsupportedEncodingExceptionche dovrai gestire. Qualcosa come questo:

public String openFileToString(String fileName) {
    String file_string;
    try {
        file_string = new String(_bytes, "UTF-8");
    } catch (UnsupportedEncodingException e) {
        // this should never happen because "UTF-8" is hard-coded.
        throw new IllegalStateException(e);
    }
    return file_string;
}

2

Ecco una funzione semplificata che leggerà in byte e creerà una stringa. Presuppone che probabilmente tu sappia già in quale codifica si trova il file (e altrimenti impostazioni predefinite).

static final int BUFF_SIZE = 2048;
static final String DEFAULT_ENCODING = "utf-8";

public static String readFileToString(String filePath, String encoding) throws IOException {

    if (encoding == null || encoding.length() == 0)
        encoding = DEFAULT_ENCODING;

    StringBuffer content = new StringBuffer();

    FileInputStream fis = new FileInputStream(new File(filePath));
    byte[] buffer = new byte[BUFF_SIZE];

    int bytesRead = 0;
    while ((bytesRead = fis.read(buffer)) != -1)
        content.append(new String(buffer, 0, bytesRead, encoding));

    fis.close();        
    return content.toString();
}

Codice modificato per rendere predefinito il valore utf-8 in modo che corrisponda alla domanda del PO.
scottt,

1

String ha un costruttore che accetta byte [] e charsetname come parametri :)


0

Ciò comporta anche l'iterazione, ma è molto meglio che concatenare le stringhe poiché sono molto costose.

public String openFileToString(String fileName)
{
    StringBuilder s = new StringBuilder(_bytes.length);

    for(int i = 0; i < _bytes.length; i++)
    {
        s.append((char)_bytes[i]);
    }

    return s.toString();    
}

8
mio caro signore. String str = new String(byte[])andrà bene.
zengr,

3
Ciò migliora l'efficienza, ma non decodifica correttamente i dati utf8.
Ted Hopp,

0

Perché non ottenere ciò che stai cercando fin dall'inizio e leggere una stringa dal file anziché un array di byte? Qualcosa di simile a:

BufferedReader in = new BufferedReader(new InputStreamReader( new FileInputStream( "foo.txt"), Charset.forName( "UTF-8"));

quindi leggi Linea da dentro fino a quando non è terminato.


A volte, è utile mantenere i delimitatori di linea originali. L'OP potrebbe volerlo.
Bruno,

0

Uso così

String strIn = new String(_bytes, 0, numBytes);


1
Questo non specifica un set di caratteri in modo da ottenere il set di caratteri predefinito della piattaforma che potrebbe non essere UTF-8.
Greg-449,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.