He estado usando el modismo a continuación por algún tiempo ahora. Y parece ser el más extendido, al menos en los sitios que he visitado.
¿Hay una manera 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();
}
}
byte[] Files.readAllBytes(file);
a aquellos que sugieren la solución de escáner 'de una línea': ¿no es necesario cerrarla?Respuestas:
Leer todo el texto de un archivo
Java 11 agregó el método readString () para leer archivos pequeños como
String
terminadores de línea de preservación:Para las versiones entre Java 7 y 11, aquí hay un idioma compacto y robusto, envuelto en un método de utilidad:
Leer líneas de texto de un archivo
Java 7 agregó un método conveniente para leer un archivo como líneas de texto, representado como a
List<String>
. Este enfoque es "con pérdida" porque los separadores de línea se eliminan del final de cada línea.Java 8 agregó el
Files.lines()
método para producir aStream<String>
. Nuevamente, este método es con pérdida porque los separadores de línea se eliminan. SiIOException
se encuentra un mensaje al leer el archivo, se envuelve en unUncheckedIOException
, yaStream
que no acepta lambdas que arrojan excepciones marcadas.Esto
Stream
necesita unaclose()
llamada; esto está mal documentado en la API, y sospecho que muchas personas ni siquiera notan queStream
tiene unclose()
método. Asegúrese de usar un bloque ARM como se muestra.Si está trabajando con una fuente que no sea un archivo, puede utilizar el
lines()
método en suBufferedReader
lugar.Utilización de la memoria
El primer método, que preserva los saltos de línea, puede requerir temporalmente memoria varias veces el tamaño del archivo, porque por un corto tiempo el contenido del archivo sin formato (una matriz de bytes) y los caracteres decodificados (cada uno de los cuales es de 16 bits, incluso si está codificado como 8 bits en el archivo) residen en la memoria a la vez. Es más seguro aplicarlo a archivos que sabe que son pequeños en relación con la memoria disponible.
El segundo método, la lectura de líneas, suele ser más eficiente en la memoria, ya que el búfer de bytes de entrada para la decodificación no necesita contener todo el archivo. Sin embargo, todavía no es adecuado para archivos que son muy grandes en relación con la memoria disponible.
Para leer archivos grandes, necesita un diseño diferente para su programa, uno que lea un fragmento de texto de una secuencia, lo procese y luego pase al siguiente, reutilizando el mismo bloque de memoria de tamaño fijo. Aquí, "grande" depende de las especificaciones de la computadora. Hoy en día, este umbral podría ser de muchos gigabytes de RAM. El tercer método, usar a
Stream<String>
es una forma de hacerlo, si los "registros" de entrada son líneas individuales. (El uso delreadLine()
método deBufferedReader
es el equivalente procesal a este enfoque).Codificación de caracteres
Una cosa que falta en la muestra en la publicación original es la codificación de caracteres. Hay algunos casos especiales en los que el valor predeterminado de la plataforma es lo que desea, pero son raros y debería poder justificar su elección.
La
StandardCharsets
clase define algunas constantes para las codificaciones requeridas de todos los tiempos de ejecución de Java:El valor predeterminado de la plataforma está disponible desde la
Charset
propia clase :Nota: Esta respuesta reemplaza en gran medida mi versión de Java 6. La utilidad de Java 7 simplifica de forma segura el código, y la respuesta anterior, que usaba un búfer de bytes mapeado, evitó que el archivo que se leía se eliminara hasta que el búfer mapeado se recogiera basura. Puede ver la versión anterior a través del enlace "editado" en esta respuesta.
fuente
FileChannel#map
, en general, es inutilizable.Si está dispuesto a usar una biblioteca externa, consulte Apache Commons IO (200KB JAR). Contiene un
org.apache.commons.io.FileUtils.readFileToString()
método que le permite leer un todoFile
en unaString
con una línea de código.Ejemplo:
fuente
Una solución muy magra basada en
Scanner
:O, si desea configurar el juego de caracteres:
O, con un bloque de prueba con recursos , que llamará
scanner.close()
por usted:Recuerde que el
Scanner
constructor puede lanzar unIOException
. Y no olvides importarjava.io
yjava.util
.Fuente: blog de Pat Niemeyer
fuente
java.util.NoSuchElementException
.desde java 7 puedes hacerlo de esta manera.
fuente
Si está buscando una alternativa que no implique una biblioteca de terceros (p. Ej., E / S de Commons ), puede usar la clase Escáner :
fuente
Scanner scanner = new Scanner((Readable) new BufferedReader(new FileReader(file)));
. De lo contrario, solo puede capturar parte del archivo.La guayaba tiene un método similar al de Commons IOUtils que Willi aus Rohr mencionó:
EDITAR por PiggyPiglet
Files#toString
está en desuso y se debe eliminar Octobor 2019. En su lugar, useFiles.asCharSource(new File(path), StandardCharsets.UTF_8).read();
EDITAR por Oscar Reyes
Este es el código subyacente (simplificado) en la biblioteca citada:
Editar (por Jonik): lo anterior no coincide con el código fuente de las versiones recientes de Guava. Para la fuente actual, consulte las clases Archivos , CharStreams , ByteSource y CharSource en el paquete com.google.common.io .
fuente
Closer
en CharSource . El código en la respuesta no es la fuente actual y actual de Guava........
fuente
new String(Files.readAllBytes(FileSystems.getDefault().getPath( filename)));
new String(Files.readAllBytes(Paths.get(filename)));
:-)Paths
aparentemente es 1.7+ como esFileSystems
. (¡Si necesita un procesamiento de cadena (procesamiento paralelo) Java 8 tiene la gran API Stream.
Hay más ejemplos disponibles en muestras JDK
sample/lambda/BulkDataOperations
que se pueden descargar desde la página de descarga de Oracle Java SE 8Otro ejemplo de un trazador de líneas
fuente
Ese código normalizará los saltos de línea, que pueden o no ser lo que realmente quieres hacer.
Aquí hay una alternativa que no hace eso, y que es (IMO) más simple de entender que el código NIO (aunque todavía usa
java.nio.charset.Charset
):fuente
Reunió todas las formas posibles de leer el archivo como cadena desde el disco o la red.
Guayaba: Google usando clases
Resources
,Files
APACHE - COMMONS IO usando las clases IOUtils, FileUtils
Java 8 BufferReader usando Stream API
Clase de escáner con expresiones regulares
\A
. que coincide con el comienzo de la entrada.Java 7 (
java.nio.file.Files.readAllBytes
)BufferedReader
utilizandoInputStreamReader
.Ejemplo con método principal para acceder a los métodos anteriores.
@ver
fuente
Si es un archivo de texto, ¿por qué no usar apache commons-io ?
Tiene el siguiente método
Si quieres las líneas como una lista usa
fuente
Desde JDK 11:
fuente
Para leer un archivo como binario y convertir al final
fuente
Con Java 7, esta es mi opción preferida para leer un archivo UTF-8:
Desde Java 7, el JDK tiene la nueva
java.nio.file
API, que proporciona muchos accesos directos, por lo que las bibliotecas de terceros no siempre son necesarias para las operaciones de archivos simples.fuente
Java intenta ser extremadamente general y flexible en todo lo que hace. Como resultado, algo que es relativamente simple en un lenguaje de script (su código sería reemplazado por "
open(file).read()
" en python) es mucho más complicado. No parece haber una forma más corta de hacerlo, excepto el uso de una biblioteca externa (como mencionó Willi aus Rohr ). Sus opciones:Su mejor apuesta es probablemente la segunda, ya que tiene menos dependencias.
fuente
byte[] bytes = Files.readAllBytes(someFile.toPath());
Usando JDK 8 o superior:
no se usan bibliotecas externas
Puede crear un nuevo objeto String a partir del contenido del archivo (Usar clases del
java.nio.file
paquete):fuente
Existe una variación sobre el mismo tema que utiliza un bucle for, en lugar de un bucle while, para limitar el alcance de la variable de línea. Si es "mejor" es una cuestión de gusto personal.
fuente
line
variable. La edición lo declaró dos veces, lo que sería un error de compilación.Si no tiene acceso a la
Files
clase, puede usar una solución nativa.fuente
Una solución flexible que utiliza IOUtils de Apache commons-io en combinación con StringWriter :
Funciona con cualquier lector o flujo de entrada (no solo con archivos), por ejemplo, cuando se lee desde una URL.
fuente
Tenga en cuenta que el uso
fileInputStream.available()
del número entero devuelto no tiene que representar el tamaño real del archivo, sino la cantidad adivinada de bytes que el sistema debería poder leer de la secuencia sin bloquear las E / S. Una forma segura y simple podría verse asíDebe considerarse que este enfoque no es adecuado para codificaciones de caracteres de varios bytes como UTF-8.
fuente
available()
método, no hay garantía de que se alcance el final del archivo en el caso de que el método devuelva 0. En ese caso, podría terminar con un archivo incompleto. Lo que es peor, el número de bytes realmente leídos puede ser menor que el valor devueltoavailable()
, en cuyo caso se corrompe la salida.Este usa el método
RandomAccessFile.readFully
, ¡parece estar disponible desde JDK 1.0!fuente
Puedes probar Scanner y File class, una solución de pocas líneas
fuente
Usuario
java.nio.Files
para leer todas las líneas de archivo.fuente
fuente
cannot find symbol
.Todavía no puedo comentar otras entradas, así que lo dejaré aquí.
Una de las mejores respuestas aquí ( https://stackoverflow.com/a/326448/1521167 ):
Todavía tiene un defecto. Siempre pone una nueva línea de caracteres al final de la cadena, lo que puede causar algunos errores extraños. Mi sugerencia es cambiarlo a:
fuente
Después de Ctrl + F'ing después del escáner, creo que la solución del escáner también debería aparecer en la lista. De la manera más fácil de leer, es así:
Si usa Java 7 o más reciente (y realmente debería hacerlo), considere usar try-with-resources para que el código sea más fácil de leer. No más cosas de punto cerrado que ensucian todo. Pero eso es principalmente una elección estilística, creo.
Estoy publicando esto principalmente para completar, ya que si necesita hacer esto mucho, debería haber cosas en java.nio.file.Files que deberían hacer el trabajo mejor.
Mi sugerencia sería usar Files # readAllBytes (Path) para capturar todos los bytes y alimentarlo a una nueva cadena (byte [] Charset) para obtener una cadena en la que pueda confiar. Los charsets serán malos para ti durante tu vida, así que ten cuidado con estas cosas ahora.
Otros han dado código y esas cosas, y no quiero robarles su gloria. ;)
fuente
Usando esta biblioteca , es una línea:
fuente
Además, si su archivo está dentro de un jar, también puede usar esto:
La ruta debería comenzar,
/
por ejemplo, si su jarra esEntonces quieres invocarlo así:
fuente
En una línea (Java 8), suponiendo que tenga un Reader:
fuente
Según la respuesta de @ erickson, puede usar:
fuente