UTF - 8 byte [] a cadena


Supongamos que acabo de usar un BufferedInputStream para leer los bytes de un archivo de texto codificado UTF-8 en una matriz de bytes. Sé que puedo usar la siguiente rutina para convertir los bytes en una cadena, pero ¿hay una forma más eficiente/inteligente de hacer esto que simplemente iterar a través de los bytes y convertir cada uno?

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

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

    return file_string;    
}
 217
Author: Raedwald, 2011-12-15

11 answers

Mira el constructor para String

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

Y si te sientes perezoso, puedes usar la biblioteca Apache Commons IO para convertir el flujo de entrada a una cadena directamente:

String str = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
 457
Author: Jason Nichols,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-24 23:52:22

La clase String de Java tiene un constructor integrado para convertir la matriz de bytes en string.

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

String value = new String(byteArray, "UTF-8");
 38
Author: Kashif Khan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-11 12:52:41

Para convertir datos utf-8, no puede asumir una correspondencia 1-1 entre bytes y caracteres. Prueba esto:

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

(Bah. Veo que soy muy lento al presionar el botón Publicar Tu respuesta.)

Para leer un archivo completo como una cadena, haga algo como esto:

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
        }
    }
}
 8
Author: Ted Hopp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-12-14 22:04:58

Puedes usar el constructor String(byte[] bytes) para eso. Vea este enlace para más detalles. EDIT También debe considerar el conjunto de caracteres predeterminado de su plataforma según el documento de java:

Construye una nueva cadena decodificando la matriz de bytes especificada usando el conjunto de caracteres predeterminado de la plataforma. La longitud de la nueva cadena es una función del conjunto de caracteres, y por lo tanto puede no ser igual a la longitud de la matriz de bytes. El comportamiento de este constructor cuando los bytes dados no válido en el conjunto de caracteres predeterminado no está especificado. El CharsetDecoder se debe utilizar cuando más control sobre el se requiere un proceso de decodificación.

 4
Author: GETah,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-12-14 21:54:27

Puede usar los métodos descritos en esta pregunta (especialmente porque comienza con un flujo de entrada): Leer / convertir un flujo de entrada en una cadena

En particular, si no desea confiar en bibliotecas externas, puede probar esta respuesta , que lee el InputStream a través de un InputStreamReader en un búfer char[] y lo añade a un StringBuilder.

 2
Author: Bruno,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:18:26

Aquí hay una función simplificada que leerá en bytes y creará una cadena. Asume que probablemente ya sabes en qué codificación está el archivo (y de lo contrario los valores predeterminados).

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();
}
 2
Author: scottt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-03-10 00:03:02

String tiene un constructor que toma byte [] y charsetname como parámetros:)

 1
Author: soulcheck,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-12-14 21:49:40

Sabiendo que está tratando con una matriz de bytes UTF-8, definitivamente querrá usar el constructor de cadenas que acepta un nombre de conjunto de caracteres. De lo contrario, puede dejarse abierto a algunas vulnerabilidades de seguridad basadas en codificación de conjuntos de caracteres. Tenga en cuenta que lanza UnsupportedEncodingException que tendrás que manejar. Algo como esto:

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;
}
 1
Author: Asaph,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-12-14 21:59:11

Esto también implica iterar, pero esto es mucho mejor que concatenar cadenas, ya que son muy, muy costosas.

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();    
}
 0
Author: bragboy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-12-14 21:49:24

¿Por qué no obtener lo que está buscando desde el principio y leer una cadena del archivo en lugar de una matriz de bytes? Algo como:

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

Luego readLine desde adentro hasta que esté hecho.

 0
Author: digitaljoel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-12-14 22:01:47

Yo uso de esta manera

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

 0
Author: Anatoliy Pelepetz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-17 10:21:40