/* * Copyright (c) 2001 Matthew Feldt. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided the copyright notice above is * retained. * * THIS SOFTWARE IS PROVIDED ''AS IS'' AND WITHOUT ANY EXPRESSED OR * IMPLIED WARRANTIES. */ /** * Tail.java * * Java Examples In A Nutshell Copyright (c) 2000 David Flanagan * Exercise 3-2: * Write a corresponding program named Tail that prints out the last 10 lines * of each file specified on the command line. * * Note: contains a correction and enhancement inspired by raghu * * @author Matthew Feldt * @version 1.1, 07/25/2002 12:12 */ package com.feldt.examples.io; import java.io.*; public class Tail { public static void main (String args[]) { final int NUM_LINES = 10, BUFSIZE = 1024; long pos, endPos, lastPos; int lineCounter = 0; byte[] buffer = new byte[BUFSIZE]; RandomAccessFile in; for (int i = 0; i < args.length; i++) { try { File f = new File(args[i]); if (! f.exists()) fail(args[i] + ": no such file or directory."); if (! f.canRead()) fail(args[i] + ": read protected."); if (! f.isFile()) fail(args[i] + ": is not a regular file."); in = new RandomAccessFile(f, "r"); endPos = in.length(); // determine file length lastPos = endPos; // initialize lastPos to end of file // guarantee a non-empty file before checking if the very // last character is a newline, count one if not if (endPos > 0) { byte[] oneByte = new byte[1]; in.seek(endPos-1); in.read(oneByte); if ((char)oneByte[0] != '\n') lineCounter++; } do { // seek cursor back BUFSIZE bytes or to beginning of // file if there aren't BUFSIZE bytes remaining pos = ((lastPos-BUFSIZE) > 0) ? lastPos - BUFSIZE : 0; in.seek(pos); // if there aren't BUFSIZE bytes left, adjust buffer to // read the remaining bytes if ((lastPos-pos) < BUFSIZE) buffer = new byte[(int)(lastPos-pos)]; // read bytes in to buffer in.readFully(buffer); // read backwards through the buffer counting newlines for (int j = buffer.length-1; j >= 0; j--) { if ((char)buffer[j] == '\n') { lineCounter++; if (lineCounter > NUM_LINES) { pos += (j+1); break; } } } // update lastPos before looping lastPos = pos; } while((lineCounter <= NUM_LINES) && (pos != 0)); // get here after determining where to start printing for (pos = lastPos; pos < endPos; pos += buffer.length) { in.seek(pos); if ((endPos-pos) < BUFSIZE) buffer = new byte[(int)(endPos-pos)]; in.readFully(buffer); System.out.print(new String(buffer)); } } catch(EOFException e) { System.err.println("EOFException: " + e.getMessage()); } catch(IOException e) { System.err.println(e.getMessage()); } catch(IllegalArgumentException e) { System.err.println(e.getMessage()); } } } /** shorthand method to throw an exception with the appropriate message */ protected static void fail(String msg) throws IllegalArgumentException { throw new IllegalArgumentException(msg); } }