Sin bucles: {{{Scanner sc = nuevo escáner (archivo, "UTF-8"); sc.useDelimiter ("$ ^"); // expresiones regulares que no coinciden con nada String text = sc.next (); sc.close (); }}}
Aivar
3
es tan interesante que no hay nada como "read ()" en python, para leer todo el archivo en una cadena
ASCII es un archivo de TEXTO que usaría Readerspara leer. Java también admite la lectura de un archivo binario usando InputStreams. Si los archivos que se leen son enormes, entonces querrá usar BufferedReaderuna FileReaderpara mejorar el rendimiento de lectura.
Elegir un lector realmente depende de para qué necesita el contenido del archivo. Si el archivo es pequeño (ish) y lo necesita todo, es más rápido (evaluado por nosotros: 1.8-2x) simplemente usar un FileReader y leer todo (o al menos fragmentos lo suficientemente grandes). Si lo está procesando línea por línea, vaya al BufferedReader.
Vlad
3
¿Se conservará el orden de las líneas al usar "Files.lines (..). ForEach (...)"? Tengo entendido que la orden será arbitraria después de esta operación.
Daniil Shevelev
39
Files.lines(…).forEach(…)no conserva el orden de las líneas pero se ejecuta en paralelo, @Dash. Si el pedido es importante, puede usarlo Files.lines(…).forEachOrdered(…), lo que debería preservar el pedido (aunque no se verificó).
Palec
2
@Palec esto es interesante, pero ¿puedes citar los documentos donde dice que Files.lines(...).forEach(...)se ejecuta en paralelo? Pensé que este era solo el caso cuando explícitamente haces que la secuencia sea paralela usando Files.lines(...).parallel().forEach(...).
Klitos Kyriacou
3
Mi formulación original no es a prueba de balas, @KlitosKyriacou. El punto es que forEachno garantiza ningún orden y la razón es la paralelización fácil. Si se debe preservar el orden, úselo forEachOrdered.
Palec
687
Mi forma favorita de leer un archivo pequeño es usar un BufferedReader y un StringBuilder. Es muy simple y al grano (aunque no particularmente efectivo, pero lo suficientemente bueno para la mayoría de los casos):
BufferedReader br =newBufferedReader(newFileReader("file.txt"));try{StringBuilder sb =newStringBuilder();String line = br.readLine();while(line !=null){
sb.append(line);
sb.append(System.lineSeparator());
line = br.readLine();}String everything = sb.toString();}finally{
br.close();}
Algunos han señalado que después de Java 7 debe usar las funciones de prueba con recursos (es decir, cierre automático):
try(BufferedReader br =newBufferedReader(newFileReader("file.txt"))){StringBuilder sb =newStringBuilder();String line = br.readLine();while(line !=null){
sb.append(line);
sb.append(System.lineSeparator());
line = br.readLine();}String everything = sb.toString();}
Cuando leo cadenas como esta, generalmente quiero hacer un poco de manejo de cadenas por línea de todos modos, así que voy por esta implementación.
Aunque si en realidad solo quiero leer un archivo en una Cadena, siempre uso Apache Commons IO con el método de clase IOUtils.toString (). Puedes echar un vistazo a la fuente aquí:
try(FileInputStream inputStream =newFileInputStream("foo.txt")){String everything =IOUtils.toString(inputStream);// do something with everything string}
He hecho un pequeño ajuste para dejar de agregar una nueva línea (\ n) si se llega a la última línea. code while (line! = null) {sb.append (line); línea = br.readLine (); // Solo agregue una nueva línea cuando curline NO sea la última línea ... if (line! = Null) {sb.append ("\ n"); }}code
Ramon Fincken
2
Similar a Apache Common IO IOUtils # toString () es sun.misc.IOUtils # readFully (), que está incluido en los JRE de Sun / Oracle.
gb96
3
Para el rendimiento, siempre llame a sb.append ('\ n') con preferencia a sb.append ("\ n") ya que un carácter se agrega al StringBuilder más rápido que un String
gb96
2
FileReader puede lanzar FileNotFoundException y BufferedRead puede lanzar IOException, por lo que debe atraparlos.
o use "try-with-resources" try (FileReader reader = new FileReader (file))
Hernán Eche
3
Noté el file.length (), ¿Qué tan bien funciona esto con los archivos utf-16?
Wayne
55
Esta técnica supone que read () llena el búfer; que el número de caracteres es igual al número de bytes; que el número de bytes cabe en la memoria; y que el número de bytes se ajusta a un número entero. -1
Marqués de Lorne
1
@HermesTrismegistus Proporcioné cuatro razones por las cuales está mal. StefanReich tiene toda la razón de estar de acuerdo conmigo.
Marqués de Lorne
35
Tuve que comparar las diferentes formas. Comentaré mis hallazgos pero, en resumen, la forma más rápida es usar un viejo BufferedInputStream simple sobre un FileInputStream. Si se deben leer muchos archivos, tres subprocesos reducirán el tiempo total de ejecución a aproximadamente la mitad, pero la adición de más subprocesos degradará progresivamente el rendimiento hasta que se tarde tres veces más en completar con veinte subprocesos que con un solo subproceso.
La suposición es que debe leer un archivo y hacer algo significativo con su contenido. En los ejemplos aquí está leyendo líneas de un registro y cuenta las que contienen valores que exceden un cierto umbral. Así que supongo que el Java 8 de una sola línea Files.lines(Paths.get("/path/to/file.txt")).map(line -> line.split(";"))no es una opción.
Probé en Java 1.8, Windows 7 y unidades SSD y HDD.
Escribí seis implementaciones diferentes:
rawParse : use BufferedInputStream sobre un FileInputStream y luego corte las líneas leyendo byte por byte. Esto superó a cualquier otro enfoque de subproceso único, pero puede ser muy inconveniente para los archivos que no son ASCII.
lineReaderParse : use un BufferedReader sobre un FileReader, lea línea por línea, divida las líneas llamando a String.split (). Esto es aproximadamente un 20% más lento que rawParse.
lineReaderParseParallel : es lo mismo que lineReaderParse, pero utiliza varios hilos. Esta es la opción más rápida en general en todos los casos.
nioFilesParse : Use java.nio.files.Files.lines ()
nioAsyncParse : utilice un AsynchronousFileChannel con un controlador de finalización y un grupo de subprocesos.
nioMemoryMappedParse : use un archivo mapeado en memoria. Esta es realmente una mala idea que genera tiempos de ejecución al menos tres veces más largos que cualquier otra implementación.
Estos son los tiempos promedio para leer 204 archivos de 4 MB cada uno en un i7 de cuatro núcleos y una unidad SSD. Los archivos se generan sobre la marcha para evitar el almacenamiento en caché del disco.
Encontré una diferencia más pequeña de lo que esperaba entre correr en un SSD o un disco duro, ya que el SSD es aproximadamente un 15% más rápido. Esto puede deberse a que los archivos se generan en un HDD no fragmentado y se leen secuencialmente, por lo tanto, la unidad giratoria puede funcionar casi como un SSD.
Me sorprendió el bajo rendimiento de la implementación de nioAsyncParse. O he implementado algo de manera incorrecta o la implementación de subprocesos múltiples usando NIO y un controlador de finalización realiza lo mismo (o incluso peor) que una implementación de subproceso único con la API java.io. Además, el análisis asíncrono con un CompletionHandler es mucho más largo en líneas de código y difícil de implementar correctamente que una implementación directa en transmisiones antiguas.
Ahora las seis implementaciones seguidas de una clase que las contiene todas más un método main () parametrizable que permite jugar con la cantidad de archivos, el tamaño del archivo y el grado de concurrencia. Tenga en cuenta que el tamaño de los archivos varía más menos 20%. Esto es para evitar cualquier efecto debido a que todos los archivos son exactamente del mismo tamaño.
rawParse
publicvoid rawParse(finalString targetDir,finalint numberOfFiles)throwsIOException,ParseException{
overrunCount =0;finalint dl =(int)';';StringBuffer lineBuffer =newStringBuffer(1024);for(int f=0; f<numberOfFiles; f++){File fl =newFile(targetDir+filenamePreffix+String.valueOf(f)+".txt");FileInputStream fin =newFileInputStream(fl);BufferedInputStream bin =newBufferedInputStream(fin);int character;while((character=bin.read())!=-1){if(character==dl){// Here is where something is done with each line
doSomethingWithRawLine(lineBuffer.toString());
lineBuffer.setLength(0);}else{
lineBuffer.append((char) character);}}
bin.close();
fin.close();}}publicfinalvoid doSomethingWithRawLine(String line)throwsParseException{// What to do for each lineint fieldNumber =0;finalint len = line.length();StringBuffer fieldBuffer =newStringBuffer(256);for(int charPos=0; charPos<len; charPos++){char c = line.charAt(charPos);if(c==DL0){String fieldValue = fieldBuffer.toString();if(fieldValue.length()>0){switch(fieldNumber){case0:Date dt = fmt.parse(fieldValue);
fieldNumber++;break;case1:double d =Double.parseDouble(fieldValue);
fieldNumber++;break;case2:int t =Integer.parseInt(fieldValue);
fieldNumber++;break;case3:if(fieldValue.equals("overrun"))
overrunCount++;break;}}
fieldBuffer.setLength(0);}else{
fieldBuffer.append(c);}}}
lineReaderParse
publicvoid lineReaderParse(finalString targetDir,finalint numberOfFiles)throwsIOException,ParseException{String line;for(int f=0; f<numberOfFiles; f++){File fl =newFile(targetDir+filenamePreffix+String.valueOf(f)+".txt");FileReader frd =newFileReader(fl);BufferedReader brd =newBufferedReader(frd);while((line=brd.readLine())!=null)
doSomethingWithLine(line);
brd.close();
frd.close();}}publicfinalvoid doSomethingWithLine(String line)throwsParseException{// Example of what to do for each lineString[] fields = line.split(";");Date dt = fmt.parse(fields[0]);double d =Double.parseDouble(fields[1]);int t =Integer.parseInt(fields[2]);if(fields[3].equals("overrun"))
overrunCount++;}
publicvoid nioFilesParse(finalString targetDir,finalint numberOfFiles)throwsIOException,ParseException{for(int f=0; f<numberOfFiles; f++){Path ph =Paths.get(targetDir+filenamePreffix+String.valueOf(f)+".txt");Consumer<String> action =newLineConsumer();Stream<String> lines =Files.lines(ph);
lines.forEach(action);
lines.close();}}classLineConsumerimplementsConsumer<String>{@Overridepublicvoid accept(String line){// What to do for each lineString[] fields = line.split(DL);if(fields.length>1){try{Date dt = fmt.parse(fields[0]);}catch(ParseException e){}double d =Double.parseDouble(fields[1]);int t =Integer.parseInt(fields[2]);if(fields[3].equals("overrun"))
overrunCount++;}}}
nioAsyncParse
publicvoid nioAsyncParse(finalString targetDir,finalint numberOfFiles,finalint numberOfThreads,finalint bufferSize)throwsIOException,ParseException,InterruptedException{ScheduledThreadPoolExecutor pool =newScheduledThreadPoolExecutor(numberOfThreads);ConcurrentLinkedQueue<ByteBuffer> byteBuffers =newConcurrentLinkedQueue<ByteBuffer>();for(int b=0; b<numberOfThreads; b++)
byteBuffers.add(ByteBuffer.allocate(bufferSize));for(int f=0; f<numberOfFiles; f++){
consumerThreads.acquire();String fileName = targetDir+filenamePreffix+String.valueOf(f)+".txt";AsynchronousFileChannel channel =AsynchronousFileChannel.open(Paths.get(fileName),EnumSet.of(StandardOpenOption.READ), pool);BufferConsumer consumer =newBufferConsumer(byteBuffers, fileName, bufferSize);
channel.read(consumer.buffer(),0l, channel, consumer);}
consumerThreads.acquire(numberOfThreads);}classBufferConsumerimplementsCompletionHandler<Integer,AsynchronousFileChannel>{privateConcurrentLinkedQueue<ByteBuffer> buffers;privateByteBuffer bytes;privateString file;privateStringBuffer chars;privateint limit;privatelong position;privateDateFormat frmt =newSimpleDateFormat("yyyy-MM-dd HH:mm:ss");publicBufferConsumer(ConcurrentLinkedQueue<ByteBuffer> byteBuffers,String fileName,int bufferSize){
buffers = byteBuffers;
bytes = buffers.poll();if(bytes==null)
bytes =ByteBuffer.allocate(bufferSize);
file = fileName;
chars =newStringBuffer(bufferSize);
frmt =newSimpleDateFormat("yyyy-MM-dd HH:mm:ss");
limit = bufferSize;
position =0l;}publicByteBuffer buffer(){return bytes;}@Overridepublicsynchronizedvoid completed(Integer result,AsynchronousFileChannel channel){if(result!=-1){
bytes.flip();finalint len = bytes.limit();int i =0;try{for(i =0; i < len; i++){byte by = bytes.get();if(by=='\n'){// ***// The code used to process the line goes here
chars.setLength(0);}else{
chars.append((char) by);}}}catch(Exception x){System.out.println("Caught exception "+ x.getClass().getName()+" "+ x.getMessage()+" i="+String.valueOf(i)+", limit="+String.valueOf(len)+", position="+String.valueOf(position));}if(len==limit){
bytes.clear();
position += len;
channel.read(bytes, position, channel,this);}else{try{
channel.close();}catch(IOException e){}
consumerThreads.release();
bytes.clear();
buffers.add(bytes);}}else{try{
channel.close();}catch(IOException e){}
consumerThreads.release();
bytes.clear();
buffers.add(bytes);}}@Overridepublicvoid failed(Throwable e,AsynchronousFileChannel channel){}};
IMPLEMENTACIÓN EJECUTABLE COMPLETA DE TODOS LOS CASOS
¿Qué quieres hacer con el texto? ¿El archivo es lo suficientemente pequeño como para caber en la memoria? Trataría de encontrar la forma más sencilla de manejar el archivo según sus necesidades. La biblioteca FileUtils es muy manejable para esto.
@PeterLawrey probablemente significa org.apache.commons.io.FileUtils. El enlace de Google puede cambiar el contenido con el tiempo, a medida que cambia el significado más extendido, pero esto coincide con su consulta y parece correcto.
Palec
2
Desafortunadamente, hoy en día no existe readLines(String)y readLines(File)está en desuso a favor readLines(File, Charset). La codificación se puede suministrar también como una cadena.
Documenté 15 formas de leer un archivo en Java y luego probé su velocidad con varios tamaños de archivo, desde 1 KB a 1 GB, y estas son las tres formas principales de hacerlo:
A continuación se muestra un resumen de cómo hacerlo en la forma Java 8. Suponiendo que el text.txtarchivo está en la raíz del directorio del proyecto de Eclipse.
import java.io.BufferedReader;import java.io.FileNotFoundException;import java.io.FileReader;import java.io.IOException;BufferedReader br;try{
br =newBufferedReader(newFileReader("/fileToRead.txt"));try{String x;while((x = br.readLine())!=null){// Printing out each line in the fileSystem.out.println(x);}}catch(IOException e){
e.printStackTrace();}}catch(FileNotFoundException e){System.out.println(e);
e.printStackTrace();}
Esto es básicamente exactamente lo mismo que la respuesta de Jesús Ramos, excepto con File en lugar de FileReader más iteración para recorrer el contenido del archivo.
Scanner in =newScanner(newFile("filename.txt"));while(in.hasNext()){// Iterates each line in the fileString line = in.nextLine();// Do something with line}
in.close();// Don't forget to close resource leaks
File vs FileReader: con un FileReader, el archivo debe existir y los permisos del sistema operativo deben permitir el acceso. Con un archivo, es posible probar esos permisos o verificar si el archivo es un directorio. El archivo tiene funciones útiles: isFile (), isDirectory (), listFiles (), canExecute (), canRead (), canWrite (), exist (), mkdir (), delete (). File.createTempFile () escribe en el directorio temporal predeterminado del sistema. Este método devolverá un objeto de archivo que se puede utilizar para abrir objetos FileOutputStream, etc. fuente
ThisClark
7
Las clases de secuencias almacenadas en búfer son mucho más eficaces en la práctica, tanto que la API NIO.2 incluye métodos que devuelven específicamente estas clases de secuencias, en parte para alentarlo a que use siempre secuencias almacenadas en su aplicación.
Aquí hay un ejemplo:
Path path =Paths.get("/myfolder/myfile.ext");try(BufferedReader reader =Files.newBufferedReader(path)){// Read from the streamString currentLine =null;while((currentLine = reader.readLine())!=null)//do your code here}catch(IOException e){// Handle file I/O exception...}
Una respuesta muy relacionada, ya existente, es de Jesús Ramos.
Palec
1
Es cierto, debería ser: if(scanner.hasNext()) content = scanner.next();
David Soroko
1
Esto me falla en Android 4.4. Solo se leen 1024 bytes. YMMV.
Roger Keays
3
Aún no lo veo mencionado en las otras respuestas hasta ahora. Pero si "Mejor" significa velocidad, entonces la nueva E / S Java (NIO) podría proporcionar el rendimiento más rápido, pero no siempre es el más fácil de descubrir para alguien que está aprendiendo.
Deberías haber dicho cómo se hace y no dar un enlace para seguir
Orar
3
La forma más sencilla de leer datos de un archivo en Java es utilizar la clase File para leer el archivo y la clase Scanner para leer el contenido del archivo.
publicstaticvoid main(String args[])throwsException{File f =newFile("input.txt");
takeInputIn2DArray(f);}publicstaticvoid takeInputIn2DArray(File f)throwsException{Scanner s =newScanner(f);int a[][]=newint[20][20];for(int i=0; i<20; i++){for(int j=0; j<20; j++){
a[i][j]= s.nextInt();}}}
PD: No olvides importar java.util. *; para que el escáner funcione.
Esta podría no ser la respuesta exacta a la pregunta. Es solo otra forma de leer un archivo en el que no especifica explícitamente la ruta a su archivo en su código Java y, en su lugar, lo lee como un argumento de línea de comandos.
Creo que readAllBytes es más rápido y más preciso, porque no reemplaza una nueva línea \ny también puede ser una nueva línea \r\n. Dependiendo de sus necesidades, cuál es el adecuado.
try{File f =newFile("filename.txt");Scanner r =newScanner(f);while(r.hasNextLine()){String data = r.nextLine();JOptionPane.showMessageDialog(data);}
r.close();}catch(FileNotFoundException ex){JOptionPane.showMessageDialog("Error occurred");
ex.printStackTrace();}
Mucho más rápido, lo dudo, si utiliza sencilla concatenación de cadenas en lugar de un StringBuilder ...
PhiLho
66
Creo que la ganancia de velocidad principal es de la lectura en bloques de 1 MB (1024 * 1024). Sin embargo, podría hacer lo mismo simplemente pasando 1024 * 1024 como segundo argumento al constructor BufferedReader.
gb96
3
No creo que esto se pruebe en absoluto. el uso +=de esta manera le brinda complejidad cuadrática (!) para una tarea que debería ser una complejidad lineal. esto comenzará a rastrear archivos de más de unos pocos mb. para evitar esto, debe mantener los bloques de texto en una lista <cadena> o usar el generador de cadenas antes mencionado.
kritzikratzi
55
¿Mucho más rápido que qué? Sin duda, no es más rápido que agregar un StringBuffer. -1
Marqués de Lorne
1
@ gb96 Pensé lo mismo sobre los tamaños de búfer, pero el experimento detallado en esta pregunta dio resultados sorprendentes en un contexto similar: un búfer de 16 KB fue consistente y notablemente más rápido.
chiastic-security
-3
String fileName ='yourFileFullNameWithPath';File file =newFile(fileName);// Creates a new file object for your fileFileReader fr =newFileReader(file);// Creates a Reader that you can use to read the contents of a file read your fileBufferedReader br =newBufferedReader(fr);//Reads text from a character-input stream, buffering characters so as to provide for the efficient reading of characters, arrays, and lines.
El conjunto de líneas anterior se puede escribir en 1 sola línea como:
Respuestas:
ASCII es un archivo de TEXTO que usaría
Readers
para leer. Java también admite la lectura de un archivo binario usandoInputStreams
. Si los archivos que se leen son enormes, entonces querrá usarBufferedReader
unaFileReader
para mejorar el rendimiento de lectura.Lee este artículo sobre cómo usar un
Reader
También te recomiendo que descargues y leas este libro maravilloso (pero gratuito) llamado Pensamiento en Java
En Java 7 :
(docs) o
(documentos)
En Java 8 :
(documentos)
fuente
Files.lines(…).forEach(…)
no conserva el orden de las líneas pero se ejecuta en paralelo, @Dash. Si el pedido es importante, puede usarloFiles.lines(…).forEachOrdered(…)
, lo que debería preservar el pedido (aunque no se verificó).Files.lines(...).forEach(...)
se ejecuta en paralelo? Pensé que este era solo el caso cuando explícitamente haces que la secuencia sea paralela usandoFiles.lines(...).parallel().forEach(...)
.forEach
no garantiza ningún orden y la razón es la paralelización fácil. Si se debe preservar el orden, úseloforEachOrdered
.Mi forma favorita de leer un archivo pequeño es usar un BufferedReader y un StringBuilder. Es muy simple y al grano (aunque no particularmente efectivo, pero lo suficientemente bueno para la mayoría de los casos):
Algunos han señalado que después de Java 7 debe usar las funciones de prueba con recursos (es decir, cierre automático):
Cuando leo cadenas como esta, generalmente quiero hacer un poco de manejo de cadenas por línea de todos modos, así que voy por esta implementación.
Aunque si en realidad solo quiero leer un archivo en una Cadena, siempre uso Apache Commons IO con el método de clase IOUtils.toString (). Puedes echar un vistazo a la fuente aquí:
http://www.docjar.com/html/api/org/apache/commons/io/IOUtils.java.html
E incluso más simple con Java 7:
fuente
code
while (line! = null) {sb.append (line); línea = br.readLine (); // Solo agregue una nueva línea cuando curline NO sea la última línea ... if (line! = Null) {sb.append ("\ n"); }}code
La forma más fácil es usar la
Scanner
clase en Java y el objeto FileReader. Ejemplo simple:Scanner
tiene varios métodos para leer en cadenas, números, etc. Puede buscar más información sobre esto en la página de documentación de Java.Por ejemplo, leer todo el contenido en un
String
:Además, si necesita una codificación específica, puede usar esto en lugar de
FileReader
:fuente
BufferedReader
while ((line = br.readLine()) != null) { sb.append(line); }
?Aquí hay una solución simple:
fuente
Aquí hay otra forma de hacerlo sin usar bibliotecas externas:
fuente
Tuve que comparar las diferentes formas. Comentaré mis hallazgos pero, en resumen, la forma más rápida es usar un viejo BufferedInputStream simple sobre un FileInputStream. Si se deben leer muchos archivos, tres subprocesos reducirán el tiempo total de ejecución a aproximadamente la mitad, pero la adición de más subprocesos degradará progresivamente el rendimiento hasta que se tarde tres veces más en completar con veinte subprocesos que con un solo subproceso.
La suposición es que debe leer un archivo y hacer algo significativo con su contenido. En los ejemplos aquí está leyendo líneas de un registro y cuenta las que contienen valores que exceden un cierto umbral. Así que supongo que el Java 8 de una sola línea
Files.lines(Paths.get("/path/to/file.txt")).map(line -> line.split(";"))
no es una opción.Probé en Java 1.8, Windows 7 y unidades SSD y HDD.
Escribí seis implementaciones diferentes:
rawParse : use BufferedInputStream sobre un FileInputStream y luego corte las líneas leyendo byte por byte. Esto superó a cualquier otro enfoque de subproceso único, pero puede ser muy inconveniente para los archivos que no son ASCII.
lineReaderParse : use un BufferedReader sobre un FileReader, lea línea por línea, divida las líneas llamando a String.split (). Esto es aproximadamente un 20% más lento que rawParse.
lineReaderParseParallel : es lo mismo que lineReaderParse, pero utiliza varios hilos. Esta es la opción más rápida en general en todos los casos.
nioFilesParse : Use java.nio.files.Files.lines ()
nioAsyncParse : utilice un AsynchronousFileChannel con un controlador de finalización y un grupo de subprocesos.
nioMemoryMappedParse : use un archivo mapeado en memoria. Esta es realmente una mala idea que genera tiempos de ejecución al menos tres veces más largos que cualquier otra implementación.
Estos son los tiempos promedio para leer 204 archivos de 4 MB cada uno en un i7 de cuatro núcleos y una unidad SSD. Los archivos se generan sobre la marcha para evitar el almacenamiento en caché del disco.
Encontré una diferencia más pequeña de lo que esperaba entre correr en un SSD o un disco duro, ya que el SSD es aproximadamente un 15% más rápido. Esto puede deberse a que los archivos se generan en un HDD no fragmentado y se leen secuencialmente, por lo tanto, la unidad giratoria puede funcionar casi como un SSD.
Me sorprendió el bajo rendimiento de la implementación de nioAsyncParse. O he implementado algo de manera incorrecta o la implementación de subprocesos múltiples usando NIO y un controlador de finalización realiza lo mismo (o incluso peor) que una implementación de subproceso único con la API java.io. Además, el análisis asíncrono con un CompletionHandler es mucho más largo en líneas de código y difícil de implementar correctamente que una implementación directa en transmisiones antiguas.
Ahora las seis implementaciones seguidas de una clase que las contiene todas más un método main () parametrizable que permite jugar con la cantidad de archivos, el tamaño del archivo y el grado de concurrencia. Tenga en cuenta que el tamaño de los archivos varía más menos 20%. Esto es para evitar cualquier efecto debido a que todos los archivos son exactamente del mismo tamaño.
rawParse
lineReaderParse
lineReaderParseParallel
nioFilesParse
nioAsyncParse
IMPLEMENTACIÓN EJECUTABLE COMPLETA DE TODOS LOS CASOS
https://github.com/sergiomt/javaiobenchmark/blob/master/FileReadBenchmark.java
fuente
Aquí están los tres métodos de trabajo y probados:
Utilizando
BufferedReader
Utilizando
Scanner
Utilizando
FileReader
Lea todo el archivo sin bucle usando la
Scanner
clasefuente
java.nio.file.Files
? Podemos ahora sólo tiene que utilizarreadAllLines
,readAllBytes
ylines
.Los métodos dentro
org.apache.commons.io.FileUtils
también pueden ser muy útiles, por ejemplo:fuente
¿Qué quieres hacer con el texto? ¿El archivo es lo suficientemente pequeño como para caber en la memoria? Trataría de encontrar la forma más sencilla de manejar el archivo según sus necesidades. La biblioteca FileUtils es muy manejable para esto.
fuente
org.apache.commons.io.FileUtils
. El enlace de Google puede cambiar el contenido con el tiempo, a medida que cambia el significado más extendido, pero esto coincide con su consulta y parece correcto.readLines(String)
yreadLines(File)
está en desuso a favorreadLines(File, Charset)
. La codificación se puede suministrar también como una cadena.Documenté 15 formas de leer un archivo en Java y luego probé su velocidad con varios tamaños de archivo, desde 1 KB a 1 GB, y estas son las tres formas principales de hacerlo:
java.nio.file.Files.readAllBytes()
Probado para trabajar en Java 7, 8 y 9.
java.io.BufferedReader.readLine()
Probado para trabajar en Java 7, 8, 9.
java.nio.file.Files.lines()
Esto se probó para funcionar en Java 8 y 9, pero no funcionará en Java 7 debido al requisito de expresión lambda.
fuente
A continuación se muestra un resumen de cómo hacerlo en la forma Java 8. Suponiendo que el
text.txt
archivo está en la raíz del directorio del proyecto de Eclipse.fuente
Usando BufferedReader:
fuente
Esto es básicamente exactamente lo mismo que la respuesta de Jesús Ramos, excepto con File en lugar de FileReader más iteración para recorrer el contenido del archivo.
... tira
FileNotFoundException
fuente
Las clases de secuencias almacenadas en búfer son mucho más eficaces en la práctica, tanto que la API NIO.2 incluye métodos que devuelven específicamente estas clases de secuencias, en parte para alentarlo a que use siempre secuencias almacenadas en su aplicación.
Aquí hay un ejemplo:
Puedes reemplazar este código
con
Recomiendo este artículo para conocer los principales usos de Java NIO e IO.
fuente
Probablemente no sea tan rápido como con las E / S almacenadas, pero es bastante breve:
El
\Z
patrón indicaScanner
que el delimitador es EOF.fuente
if(scanner.hasNext()) content = scanner.next();
Aún no lo veo mencionado en las otras respuestas hasta ahora. Pero si "Mejor" significa velocidad, entonces la nueva E / S Java (NIO) podría proporcionar el rendimiento más rápido, pero no siempre es el más fácil de descubrir para alguien que está aprendiendo.
http://download.oracle.com/javase/tutorial/essential/io/file.html
fuente
La forma más sencilla de leer datos de un archivo en Java es utilizar la clase File para leer el archivo y la clase Scanner para leer el contenido del archivo.
PD: No olvides importar java.util. *; para que el escáner funcione.
fuente
La guayaba ofrece una frase para esto:
fuente
Esta podría no ser la respuesta exacta a la pregunta. Es solo otra forma de leer un archivo en el que no especifica explícitamente la ruta a su archivo en su código Java y, en su lugar, lo lee como un argumento de línea de comandos.
Con el siguiente código,
simplemente adelante y ejecútalo con:
Esto leería el contenido de la
input.txt
e imprimiría en su consola.También puede hacer
System.out.println()
que escriba en un archivo específico a través de la línea de comando de la siguiente manera:Esto leería
input.txt
y escribiría aoutput.txt
.fuente
Puede usar readAllLines y el
join
método para obtener todo el contenido del archivo en una línea:Utiliza la codificación UTF-8 de forma predeterminada, que lee los datos ASCII correctamente.
También puedes usar readAllBytes:
Creo que readAllBytes es más rápido y más preciso, porque no reemplaza una nueva línea
\n
y también puede ser una nueva línea\r\n
. Dependiendo de sus necesidades, cuál es el adecuado.fuente
Para las aplicaciones web Maven basadas en JSF, solo use ClassLoader y la
Resources
carpeta para leer el archivo que desee:Coloque la dependencia de Apache Commons IO en su POM:
Use el siguiente código para leerlo (por ejemplo, a continuación se lee en un archivo .json):
Puede hacer lo mismo para archivos de texto, archivos .properties, esquemas XSD , etc.
fuente
Cactoos te ofrece una frase declarativa:
fuente
Use Java kiss si se trata de simplicidad de estructura:
fuente
Solo usa java 8 Stream.
fuente
fuente
El método más intuitivo se introduce en Java 11
Files.readString
¡PHP tiene este lujo de hace décadas! ☺
fuente
Este código que programé es mucho más rápido para archivos muy grandes:
fuente
+=
de esta manera le brinda complejidad cuadrática (!) para una tarea que debería ser una complejidad lineal. esto comenzará a rastrear archivos de más de unos pocos mb. para evitar esto, debe mantener los bloques de texto en una lista <cadena> o usar el generador de cadenas antes mencionado.El conjunto de líneas anterior se puede escribir en 1 sola línea como:
Agregar al generador de cadenas (si el archivo es enorme, se recomienda usar el generador de cadenas; de lo contrario, use el objeto de cadena normal)
fuente