una txt texto separado por palabra linea leer lectura especifica con como comas archivos archivo java file io

java - txt - ¿Leer rápidamente la última línea de un archivo de texto?



leer un archivo txt con java (7)

Apache Commons tiene una implementación usando RandomAccessFile .

Se llama ReversedLinesFileReader .

¿Cuál es la forma más rápida y eficiente de leer la última línea de texto de un archivo [muy, muy grande] en Java?


Echa un vistazo a mi respuesta a una pregunta similar para C # . El código sería bastante similar, aunque el soporte de codificación es algo diferente en Java.

Básicamente no es algo terriblemente fácil de hacer en general. Como señala MSalter, UTF-8 hace que sea fácil de detectar /r o /n ya que la representación UTF-8 de esos caracteres es igual a ASCII, y esos bytes no ocurrirán en caracteres de múltiples bytes.

Básicamente, tome un búfer de (digamos) 2K y lea progresivamente hacia atrás (salte a 2K antes que antes, lea los próximos 2K) verificando la terminación de una línea. Luego, salte al lugar correcto en la secuencia, cree un InputStreamReader en la parte superior y un BufferedReader además de eso. Entonces solo llame a BufferedReader.readLine() .


El uso de FileReader o FileInputStream no funcionará; deberá usar FileChannel o RandomAccessFile para recorrer el archivo hacia atrás desde el final. Las codificaciones serán un problema, como dijo Jon.



Puede cambiar fácilmente el código siguiente para imprimir la última línea.

MemoryMappedFile para imprimir las últimas 5 líneas:

private static void printByMemoryMappedFile(File file) throws FileNotFoundException, IOException{ FileInputStream fileInputStream=new FileInputStream(file); FileChannel channel=fileInputStream.getChannel(); ByteBuffer buffer=channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size()); buffer.position((int)channel.size()); int count=0; StringBuilder builder=new StringBuilder(); for(long i=channel.size()-1;i>=0;i--){ char c=(char)buffer.get((int)i); builder.append(c); if(c==''/n''){ if(count==5)break; count++; builder.reverse(); System.out.println(builder.toString()); builder=null; builder=new StringBuilder(); } } channel.close(); }

RandomAccessFile para imprimir las últimas 5 líneas:

private static void printByRandomAcessFile(File file) throws FileNotFoundException, IOException{ RandomAccessFile randomAccessFile = new RandomAccessFile(file, "r"); int lines = 0; StringBuilder builder = new StringBuilder(); long length = file.length(); length--; randomAccessFile.seek(length); for(long seek = length; seek >= 0; --seek){ randomAccessFile.seek(seek); char c = (char)randomAccessFile.read(); builder.append(c); if(c == ''/n''){ builder = builder.reverse(); System.out.println(builder.toString()); lines++; builder = null; builder = new StringBuilder(); if (lines == 5){ break; } } } }


A continuación hay dos funciones, una que devuelve la última línea no en blanco de un archivo sin cargar o recorrer el archivo completo, y la otra que devuelve las últimas N líneas del archivo sin recorrer todo el archivo:

Lo que hace la cola es acercarse directamente al último carácter del archivo, luego retrocede, carácter por personaje, registrando lo que ve hasta que encuentra un salto de línea. Una vez que encuentra un salto de línea, se rompe el ciclo. Invierte lo que se grabó y lo arroja a una cadena y regresa. 0xA es la nueva línea y 0xD es el retorno de carro.

Si sus terminaciones de línea son /r/n o crlf o alguna otra "nueva línea de estilo de nueva línea doble", entonces deberá especificar n * 2 líneas para obtener las últimas n líneas porque cuenta 2 líneas para cada línea.

public String tail( File file ) { RandomAccessFile fileHandler = null; try { fileHandler = new RandomAccessFile( file, "r" ); long fileLength = fileHandler.length() - 1; StringBuilder sb = new StringBuilder(); for(long filePointer = fileLength; filePointer != -1; filePointer--){ fileHandler.seek( filePointer ); int readByte = fileHandler.readByte(); if( readByte == 0xA ) { if( filePointer == fileLength ) { continue; } break; } else if( readByte == 0xD ) { if( filePointer == fileLength - 1 ) { continue; } break; } sb.append( ( char ) readByte ); } String lastLine = sb.reverse().toString(); return lastLine; } catch( java.io.FileNotFoundException e ) { e.printStackTrace(); return null; } catch( java.io.IOException e ) { e.printStackTrace(); return null; } finally { if (fileHandler != null ) try { fileHandler.close(); } catch (IOException e) { /* ignore */ } } }

Pero probablemente no quiera la última línea, quiere las últimas N líneas, así que use esto en su lugar:

public String tail2( File file, int lines) { java.io.RandomAccessFile fileHandler = null; try { fileHandler = new java.io.RandomAccessFile( file, "r" ); long fileLength = fileHandler.length() - 1; StringBuilder sb = new StringBuilder(); int line = 0; for(long filePointer = fileLength; filePointer != -1; filePointer--){ fileHandler.seek( filePointer ); int readByte = fileHandler.readByte(); if( readByte == 0xA ) { if (filePointer < fileLength) { line = line + 1; } } else if( readByte == 0xD ) { if (filePointer < fileLength-1) { line = line + 1; } } if (line >= lines) { break; } sb.append( ( char ) readByte ); } String lastLine = sb.reverse().toString(); return lastLine; } catch( java.io.FileNotFoundException e ) { e.printStackTrace(); return null; } catch( java.io.IOException e ) { e.printStackTrace(); return null; } finally { if (fileHandler != null ) try { fileHandler.close(); } catch (IOException e) { } } }

Invoca los métodos anteriores como este:

File file = new File("D://stuff//huge.log"); System.out.println(tail(file)); System.out.println(tail2(file, 10));

Advertencia En el salvaje oeste del código Unicode, este código puede hacer que la salida de esta función salga mal. Por ejemplo, "María" en lugar de "María". Los caracteres con sombreros, acentos, caracteres chinos, etc. pueden hacer que la salida sea incorrecta porque los acentos se agregan como modificadores después del carácter. La inversión de caracteres compuestos cambia la naturaleza de la identidad del personaje en la reversión. Tendrá que hacer una batería completa de pruebas en todos los idiomas con los que planea usar esto.

Para obtener más información acerca de este problema de reversión Unicode, lea esto: http://msmvps.com/blogs/jon_skeet/archive/2009/11/02/omg-ponies-aka-humanity-epic-fail.aspx


try(BufferedReader reader = new BufferedReader(new FileReader(reqFile))) { String line = null; System.out.println("======================================"); line = reader.readLine(); //Read Line ONE line = reader.readLine(); //Read Line TWO System.out.println("first line : " + line); //Length of one line if lines are of even length int len = line.length(); //skip to the end - 3 lines reader.skip((reqFile.length() - (len*3))); //Searched to the last line for the date I was looking for. while((line = reader.readLine()) != null){ System.out.println("FROM LINE : " + line); String date = line.substring(0,line.indexOf(",")); System.out.println("DATE : " + date); //BAM!!!!!!!!!!!!!! } System.out.println(reqFile.getName() + " Read(" + reqFile.length()/(1000) + "KB)"); System.out.println("======================================"); } catch (IOException x) { x.printStackTrace(); }