¿Cómo creo una cadena Java a partir del contenido de un archivo?
He estado usando el siguiente modismo desde hace algún tiempo. Y parece ser el más extendido, al menos en los sitios que he visitado.
¿Existe una forma mejor/diferente de leer un archivo en una cadena en Java?
private String readFile(String file) throws IOException {
BufferedReader reader = new BufferedReader(new FileReader (file));
String line = null;
StringBuilder stringBuilder = new StringBuilder();
String ls = System.getProperty("line.separator");
try {
while((line = reader.readLine()) != null) {
stringBuilder.append(line);
stringBuilder.append(ls);
}
return stringBuilder.toString();
} finally {
reader.close();
}
}
Leer todo el texto de un archivo
Java 11 agregó el método readString() para leer archivos pequeños como un archivo String
, preservando los terminadores de línea:
String content = Files.readString(path, encoding);
Para las versiones entre Java 7 y 11, aquí hay un lenguaje compacto y robusto, envuelto en un método de utilidad:
static String readFile(String path, Charset encoding)
throws IOException
{
byte[] encoded = Files.readAllBytes(Paths.get(path));
return new String(encoded, encoding);
}
Leer líneas de texto de un archivo
Java 7 agregó un método conveniente para leer un archivo como líneas de texto, representadas como un archivo List<String>
. Este enfoque tiene "pérdidas" porque los separadores de línea se eliminan del final de cada línea.
List<String> lines = Files.readAllLines(Paths.get(path), encoding);
Java 8 agregó el Files.lines()
método para producir un archivo Stream<String>
. Nuevamente, este método genera pérdidas porque se eliminan los separadores de línea. Si IOException
se encuentra an mientras se lee el archivo, se envuelve en an UncheckedIOException
, ya que Stream
no acepta lambdas que arrojan excepciones marcadas.
try (Stream<String> lines = Files.lines(path, encoding)) {
lines.forEach(System.out::println);
}
Esto Stream
necesita una close()
llamada; Esto está mal documentado en la API y sospecho que muchas personas ni siquiera se dan cuenta de Stream
que existe un close()
método. Asegúrese de utilizar un bloque ARM como se muestra.
Si está trabajando con una fuente que no sea un archivo, puede utilizar el lines()
método en BufferedReader
su lugar.
Utilización de la memoria
Si su archivo es lo suficientemente pequeño en relación con la memoria disponible, leer el archivo completo de una vez podría funcionar bien. Sin embargo, si su archivo es demasiado grande, leer una línea a la vez, procesarla y luego descartarla antes de pasar a la siguiente podría ser un mejor enfoque. El procesamiento de secuencias de esta manera puede eliminar el tamaño total del archivo como factor en los requisitos de memoria.
Codificación de caracteres
Una cosa que falta en el ejemplo de la publicación original es la codificación de caracteres. Esta codificación generalmente no se puede determinar a partir del archivo en sí y requiere metadatos, como un encabezado HTTP, para transmitir esta información importante.
La StandardCharsets
clase define algunas constantes para las codificaciones requeridas de todos los tiempos de ejecución de Java:
String content = readFile("test.txt", StandardCharsets.UTF_8);
El valor predeterminado de la plataforma está disponible en laCharset
propia clase :
String content = readFile("test.txt", Charset.defaultCharset());
Hay algunos casos especiales en los que la plataforma predeterminada es la que usted desea, pero son poco frecuentes. Debería poder justificar su elección, porque la plataforma predeterminada no es portátil. Un ejemplo en el que podría ser correcto es al leer la entrada estándar o escribir la salida estándar.
Nota: esta respuesta reemplaza en gran medida mi versión de Java 6. La utilidad de Java 7 simplifica el código de forma segura, y la respuesta anterior, que utilizaba un búfer de bytes asignado, impedía que el archivo leído se eliminara hasta que el búfer asignado fuera recolectado como basura. Puede ver la versión anterior a través del enlace "editado" en esta respuesta.
Si está dispuesto a utilizar una biblioteca externa, consulte Apache Commons IO (JAR de 200 KB). Contiene un org.apache.commons.io.FileUtils.readFileToString()
método que le permite leer un archivo completo File
en una String
sola línea de código.
Ejemplo:
import java.io.*;
import java.nio.charset.*;
import org.apache.commons.io.*;
public String readFile() throws IOException {
File file = new File("data.txt");
return FileUtils.readFileToString(file, StandardCharsets.UTF_8);
}
Una solución muy sencilla basada en Scanner
:
Scanner scanner = new Scanner( new File("poem.txt") );
String text = scanner.useDelimiter("\\A").next();
scanner.close(); // Put this call in a finally block
O, si desea configurar el juego de caracteres:
Scanner scanner = new Scanner( new File("poem.txt"), "UTF-8" );
String text = scanner.useDelimiter("\\A").next();
scanner.close(); // Put this call in a finally block
O bien, con un bloque de prueba con recursosscanner.close()
, que le solicitará :
try (Scanner scanner = new Scanner( new File("poem.txt"), "UTF-8" )) {
String text = scanner.useDelimiter("\\A").next();
}
Recuerde que el Scanner
constructor puede lanzar un IOException
. Y no olvides importar java.io
y java.util
.
Fuente: blog de Pat Niemeyer