/* * This code is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ package no.geosoft.cc.io; import java.io.*; import java.nio.channels.*; import java.util.zip.*; /** * Base class for file accessors (file readers and writers). * * <p> * Features: * <ul> * <li>Logging</li> * <li>Progress monitoring</li> * <li>ASCII and binary</li> * <li>Checksum generation</li> * </ul> * * <p> * This class is not abstract as a subclass will overload only one of * readFile() and writeFile() depending wether it is a reader or a writer * class (it can only be one of the two). * * <p> * There are some convenience methods for actually accessing the files * (readLine() and write()), for more detailed access a reader class * will use the reader_/binaryReader_ and a writer will use the * writer/binaryWriter_ objects. * * @author <a href="mailto:info@geosoft.no">GeoSoft</a> */ public class FileAccessor { protected File file_; protected Object stream_; // InputStream or OutputStream protected BufferedReader reader_; protected BufferedWriter writer_; protected DataInputStream binaryReader_; protected DataOutputStream binaryWriter_; protected FileLogger logger_; protected int lineNo_; protected Checksum checksum_; private FileChannel fileChannel_; /** * Create a file accessor for the specified file and with the * specified logger instance. * * @param file File to create accessor for. * @param logger Logger. */ public FileAccessor (File file, FileLogger logger) { file_ = file; stream_ = null; reader_ = null; writer_ = null; binaryReader_ = null; binaryWriter_ = null; setLogger (logger); } /** * Create a file accessor without a logger. * * @param file File to create accessor for. */ public FileAccessor (File file) { this (file, null); } /** * Set logger. * * @param logger File accessor logger. */ public void setLogger (FileLogger logger) { logger_ = logger == null ? new DefaultLogger() : logger; } /** * Open file for reading. */ protected void openForRead() { logger_.log (FileLogger.INFO, 0, 0, "Open", file_); logger_.reportProgress (file_, 0); checksum_ = new Adler32(); try { FileInputStream fileStream = new FileInputStream (file_); fileChannel_ = fileStream.getChannel(); InputStream stream = new CheckedInputStream (fileStream, checksum_); reader_ = new BufferedReader (new InputStreamReader (stream)); binaryReader_ = new DataInputStream (new BufferedInputStream (stream)); lineNo_ = -1; stream_ = stream; } catch (IOException exception) { exception.printStackTrace(); logger_.log (FileLogger.ERROR, 0, 0, "UnableToOpen", file_); } } /** * Open file for writing. */ protected void openForWrite() { logger_.log (FileLogger.INFO, 0, 0, "Open", file_); logger_.reportProgress (file_, 0); checksum_ = new Adler32(); try { FileOutputStream fileStream = new FileOutputStream (file_); fileChannel_ = fileStream.getChannel(); OutputStream stream = new CheckedOutputStream (fileStream, checksum_); writer_ = new BufferedWriter (new OutputStreamWriter (stream)); binaryWriter_ = new DataOutputStream (new BufferedOutputStream (stream)); stream_ = stream; } catch (IOException exception) { exception.printStackTrace(); logger_.log (FileLogger.ERROR, 0, 0, "UnableToOpen", file_); } } /** * Check if the entire file has been read. * * @return True if the entire file has been read, false otherwise. */ protected boolean isDone() { return getPosition() == file_.length(); } /** * Close streams. */ protected void close() { try { if (writer_ != null) writer_.flush(); if (stream_ instanceof OutputStream) { OutputStream stream = (OutputStream) stream_; stream.flush(); stream.close(); } else { InputStream stream = (InputStream) stream_; stream.close(); } } catch (Exception exception) { logger_.log (FileLogger.ERROR, 0, 0, "UnableToClose", file_); } logger_.reportProgress (file_, (int) file_.length()); reader_ = null; writer_ = null; binaryReader_ = null; binaryWriter_ = null; stream_ = null; } /** * Return the checksum for this file. * * @return Checksum for this file. */ public long getChecksum() { return checksum_.getValue(); } /** * Return current file position. * * @return Current file position. */ protected long getPosition() { long position = 0; try { position = fileChannel_.position(); } catch (Exception exception) { } return position; } /** * Read one line from the file. * * @return Next line from the file (or null if done or an error * occured). */ public String readLine() throws IOException { if (reader_ == null) return null; String line = reader_.readLine(); lineNo_++; reportProgress(); return line; } /** * Write a line to the file. * * @param string Line to write. */ public void write (String string) throws IOException { if (writer_ == null) return; writer_.write (string, 0, string.length()); reportProgress(); } /** * Skip n bytes during read. * * @param n Number of bytes to skip. */ public void skip (long n) throws IOException { if (reader_ != null) reader_.skip (n); else if (binaryReader_ != null) binaryReader_.skipBytes ((int) n); reportProgress(); } /** * Force the progress to be reported to the logger. */ public void reportProgress() { logger_.reportProgress (file_, (int) getPosition()); } /** * To be overridden by a file reader class. * * @return File content as some java object. */ public Object readFile() { return null; } /** * To be overridden by a file writer class. * * @param object Object to write. */ public void writeFile (Object object) { } /** * Dummy logger instance in case none is specified. */ public class DefaultLogger implements FileLogger { public void log (int type, int lineNo, int columnNo, String message, Object object) { // Debgugging System.out.println (lineNo + "," + columnNo + ": " + message + ": " + object.toString()); } public void reportProgress (File file, int amount) { } } }