Sé que llegué muy tarde, pero en caso de que alguien encuentre esta pregunta: Tenga en cuenta que un archivo es solo una secuencia de bytes. Y una nueva línea es solo un carácter (dos en Windows) y un carácter es solo uno (o más, dependiendo de la codificación) byte. Y, sin tener un índice de las posiciones de un byte en un archivo, la única forma de saber dónde están esos bytes es leerlo y buscarlo. (Sin embargo, esto no significa que tenga que cargar todo el archivo en la memoria).
szgal
Respuestas:
71
A menos que tenga conocimientos previos sobre las líneas del archivo, no hay forma de acceder directamente a la línea 32 sin leer las 31 líneas anteriores.
Eso es cierto para todos los idiomas y todos los sistemas de archivos modernos.
Así que, efectivamente, simplemente leerá las líneas hasta que encuentre la 32ª.
Esto devuelve java.nio.charset.MalformedInputException: longitud de entrada = 1 cuando se usa con un valor de omisión que es 1
canadiancreed
Eso no es un problema con el código que publiqué, es un problema con la codificación de su archivo. Vea esta publicación .
aioobe
3
"Tenga en cuenta que este método está diseñado para casos simples en los que es conveniente leer todas las líneas en una sola operación. No está diseñado para leer archivos grandes". - Javadoc de Files.readAllLines ()
PragmaticProgrammer
El siguiente código requiere API nivel 26 en Android. Si nuestro mínimo es menor que este nivel, entonces no funciona
Ali Azaz Alam
38
No que yo sepa, pero lo que podría hacer es recorrer las primeras 31 líneas sin hacer nada usando la función readline () de BufferedReader
FileInputStream fs=newFileInputStream("someFile.txt");BufferedReader br =newBufferedReader(newInputStreamReader(fs));for(int i =0; i <31;++i)
br.readLine();String lineIWant = br.readLine();
Tenga en cuenta que aquí lee la línea número 30, que es la línea 31 porque comenzamos los números de línea desde 0. Por lo tanto, sugeriría cambiarlo para que coincida con la pregunta con precisión.
kiedysktos
15
Joachim tiene razón, por supuesto, y una implementación alternativa a la de Chris (para archivos pequeños solo porque carga el archivo completo) podría ser usar commons-io de Apache (aunque podría decirse que es posible que no desee introducir una nueva dependencia solo para esto, si lo encuentra útil para otras cosas también, podría tener sentido).
A pesar de que se carga todo el archivo en la memoria antes de ir a la línea 32, que puede no ser práctico con un archivo grande y sería más lento que la lectura util para encontrar la línea 32a ...
beny23
Buen punto, sí. Lo he usado en casos de prueba, donde los archivos de prueba eran pequeños, en archivos grandes, aunque, de acuerdo, no es un buen enfoque.
Charlie Collins
Publicación de respuesta actualizada para reflejar que FileUtils es una mala idea en este caso de uso si tiene un archivo grande y no necesita nada más allá de la línea X.
Charlie Collins
11
Puede probar el lector de archivos indexados (Licencia Apache 2.0). La clase IndexedFileReader tiene un método llamado readLines (int from, int to) que devuelve un SortedMap cuya clave es el número de línea y el valor es la línea que se leyó.
Aunque como se dijo en otras respuestas, no es posible llegar a la línea exacta sin conocer antes el desplazamiento (puntero). Entonces, lo logré creando un archivo de índice temporal que almacenaría los valores de compensación de cada línea. Si el archivo es lo suficientemente pequeño, puede almacenar los índices (desplazamiento) en la memoria sin necesidad de un archivo separado para él.
The offsets can be calculated by using the RandomAccessFileRandomAccessFile raf =newRandomAccessFile("myFile.txt","r");//above 'r' means open in read only modeArrayList<Integer> arrayList =newArrayList<Integer>();String cur_line ="";while((cur_line=raf.readLine())!=null){
arrayList.add(raf.getFilePointer());}//Print the 32 line//Seeks the file to the particular location from where our '32' line starts
raf.seek(raf.seek(arrayList.get(31));System.out.println(raf.readLine());
raf.close();
Complejidad : Esto es O (n) ya que lee todo el archivo una vez. Tenga en cuenta los requisitos de memoria. Si es demasiado grande para estar en la memoria, cree un archivo temporal que almacene las compensaciones en lugar de ArrayList como se muestra arriba.
Nota : Si todo lo que desea en la línea '32', solo tiene que llamar a readLine () también disponible a través de otras clases '32' veces. El enfoque anterior es útil si desea obtener una línea específica (según el número de línea, por supuesto) varias veces.
Hay algo que se necesita editar para que el código anterior funcione. Y si alguien necesita un juego de caracteres preocupado, realmente debería leer esto: stackoverflow.com/a/37275357/3198960
rufushuang
5
De otra manera.
try(BufferedReader reader =Files.newBufferedReader(Paths.get("file.txt"),StandardCharsets.UTF_8)){List<String> line = reader.lines().skip(31).limit(1).collect(Collectors.toList());
line.stream().forEach(System.out::println);}
No, a menos que en ese formato de archivo las longitudes de línea estén predeterminadas (por ejemplo, todas las líneas con una longitud fija), tendrá que iterar línea por línea para contarlas.
Si está hablando de un archivo de texto, entonces realmente no hay forma de hacerlo sin leer todas las líneas que lo preceden. Después de todo, las líneas están determinadas por la presencia de una nueva línea, por lo que debe leerse.
Use una secuencia que admita readline, y simplemente lea las primeras líneas X-1 y descargue los resultados, luego procese la siguiente.
Pero en lugar de devolver una cadena, estoy devolviendo una LinkedList de cadenas. Entonces puedo seleccionar la línea que quiero.
publicstaticLinkedList<String> readFromAssets(Context context,String filename)throwsIOException{BufferedReader reader =newBufferedReader(newInputStreamReader(context.getAssets().open(filename)));LinkedList<String>linkedList =newLinkedList<>();// do reading, usually loop until end of file readingStringBuilder sb =newStringBuilder();String mLine = reader.readLine();while(mLine !=null){
linkedList.add(mLine);
sb.append(mLine);// process line
mLine = reader.readLine();}
reader.close();return linkedList;}
no ayuda, todavía tienes que leer todas las líneas antes ... excepto que haces trampa y estableces la primera línea en 32 <g>
kleopatra
0
También puede echar un vistazo a LineNumberReader, subclase de BufferedReader. Junto con el método readline, también tiene métodos setter / getter para acceder al número de línea. Muy útil para realizar un seguimiento del número de líneas leídas, mientras lee los datos del archivo.
Están todos equivocados. Escribí esto en unos 10 segundos. Con esto me las arreglé para llamar al object.getQuestion ("linoumber") en el método principal para devolver la línea que quiera.
publicclassQuestions{File file =newFile("Question2Files/triviagame1.txt");publicQuestions(){}publicString getQuestion(int numLine)throwsIOException{BufferedReader br =newBufferedReader(newFileReader(file));String line ="";for(int i =0; i < numLine; i++){
line = br.readLine();}return line;}}
Respuestas:
A menos que tenga conocimientos previos sobre las líneas del archivo, no hay forma de acceder directamente a la línea 32 sin leer las 31 líneas anteriores.
Eso es cierto para todos los idiomas y todos los sistemas de archivos modernos.
Así que, efectivamente, simplemente leerá las líneas hasta que encuentre la 32ª.
fuente
Para archivos pequeños:
Para archivos grandes:
fuente
No que yo sepa, pero lo que podría hacer es recorrer las primeras 31 líneas sin hacer nada usando la función readline () de BufferedReader
fuente
Joachim tiene razón, por supuesto, y una implementación alternativa a la de Chris (para archivos pequeños solo porque carga el archivo completo) podría ser usar commons-io de Apache (aunque podría decirse que es posible que no desee introducir una nueva dependencia solo para esto, si lo encuentra útil para otras cosas también, podría tener sentido).
Por ejemplo:
http://commons.apache.org/io/api-release/org/apache/commons/io/FileUtils.html#readLines(java.io.File , java.lang.String)
fuente
Puede probar el lector de archivos indexados (Licencia Apache 2.0). La clase IndexedFileReader tiene un método llamado readLines (int from, int to) que devuelve un SortedMap cuya clave es el número de línea y el valor es la línea que se leyó.
Ejemplo:
El ejemplo anterior lee un archivo de texto compuesto por 50 líneas en el siguiente formato:
Descargo de responsabilidad: escribí esta biblioteca
fuente
Aunque como se dijo en otras respuestas, no es posible llegar a la línea exacta sin conocer antes el desplazamiento (puntero). Entonces, lo logré creando un archivo de índice temporal que almacenaría los valores de compensación de cada línea. Si el archivo es lo suficientemente pequeño, puede almacenar los índices (desplazamiento) en la memoria sin necesidad de un archivo separado para él.
También visite los documentos de Java para obtener más información: https://docs.oracle.com/javase/8/docs/api/java/io/RandomAccessFile.html#mode
Complejidad : Esto es O (n) ya que lee todo el archivo una vez. Tenga en cuenta los requisitos de memoria. Si es demasiado grande para estar en la memoria, cree un archivo temporal que almacene las compensaciones en lugar de ArrayList como se muestra arriba.
Nota : Si todo lo que desea en la línea '32', solo tiene que llamar a readLine () también disponible a través de otras clases '32' veces. El enfoque anterior es útil si desea obtener una línea específica (según el número de línea, por supuesto) varias veces.
Gracias !
fuente
De otra manera.
fuente
No, a menos que en ese formato de archivo las longitudes de línea estén predeterminadas (por ejemplo, todas las líneas con una longitud fija), tendrá que iterar línea por línea para contarlas.
fuente
Si está hablando de un archivo de texto, entonces realmente no hay forma de hacerlo sin leer todas las líneas que lo preceden. Después de todo, las líneas están determinadas por la presencia de una nueva línea, por lo que debe leerse.
Use una secuencia que admita readline, y simplemente lea las primeras líneas X-1 y descargue los resultados, luego procese la siguiente.
fuente
En Java 8,
Para archivos pequeños:
Para archivos grandes:
En Java 7
Fuente: lectura de la enésima línea del archivo
fuente
fuente
Me funciona: he combinado la respuesta de Leer un archivo de texto simple
Pero en lugar de devolver una cadena, estoy devolviendo una LinkedList de cadenas. Entonces puedo seleccionar la línea que quiero.
fuente
Utilice este código:
fuente
Puede utilizar LineNumberReader en lugar de BufferedReader. Revisa la api. Puede encontrar los métodos setLineNumber y getLineNumber.
fuente
También puede echar un vistazo a LineNumberReader, subclase de BufferedReader. Junto con el método readline, también tiene métodos setter / getter para acceder al número de línea. Muy útil para realizar un seguimiento del número de líneas leídas, mientras lee los datos del archivo.
fuente
puede utilizar la función skip () para omitir las líneas desde el principio.
fuente
Están todos equivocados. Escribí esto en unos 10 segundos. Con esto me las arreglé para llamar al object.getQuestion ("linoumber") en el método principal para devolver la línea que quiera.
fuente