File file = new File("DemoRandomAccessFile.out"); RandomAccessFile raf = new RandomAccessFile(file, "r"); // Seek to the end of file raf.seek(file.length() - n); // Read it out. raf.read(yourbyteArray, 0, n);
Below are two functions, one that returns the last non-blank line of a file without loading or stepping through the entire file, and the other that returns the last N lines of the file without stepping through the entire file: java
What tail does is zoom straight to the last character of the file, then steps backward, character by character, recording what it sees until it finds a line break. Once it finds a line break, it breaks out of the loop. Reverses what was recorded and throws it into a string and returns. 0xA is the new line and 0xD is the carriage return. app
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; } else { break; } } else if( readByte == 0xD ) { if( filePointer == fileLength - 1 ) { continue; } else { 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 */ } } }
But you probably don't want the last line, you want the last N lines, so use this instead: dom
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 (line == lines) { if (filePointer == fileLength) { continue; } else { break; } } } else if( readByte == 0xD ) { line = line + 1; if (line == lines) { if (filePointer == fileLength - 1) { continue; } else { break; } } } sb.append( ( char ) readByte ); } sb.deleteCharAt(sb.length()-1); 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 */ } } }
Another Example oop
public static void main(String[] args) throws Exception { int n = 3; List<String> lines = new ArrayList<>(); try (RandomAccessFile f = new RandomAccessFile("test", "r")) { ByteArrayOutputStream bout = new ByteArrayOutputStream(); for (long length = f.length(), p = length - 1; p > 0 && lines.size() < n; p--) { f.seek(p); int b = f.read(); if (b == 10) { if (p < length - 1) { lines.add(0, getLine(bout)); bout.reset(); } } else if (b != 13) { bout.write(b); } } } System.out.println(lines); } static String getLine(ByteArrayOutputStream bout) { byte[] a = bout.toByteArray(); // reverse bytes for (int i = 0, j = a.length - 1; j > i; i++, j--) { byte tmp = a[j]; a[j] = a[i]; a[i] = tmp; } return new String(a); }