/* * Geotools - OpenSource mapping toolkit * * (C) 2002-2008, Open Source Geospatial Foundation (OSGeo) * * This library 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; * version 2.1 of the License. * * This library 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. * * This file is based on an origional contained in the GISToolkit project: * http://gistoolkit.sourceforge.net/ */ package org.geotools.data.shapefile.dbf; import java.io.IOException; import java.nio.channels.FileChannel; import java.nio.channels.FileChannel.MapMode; import java.nio.charset.Charset; import java.util.TimeZone; import org.geotools.data.shapefile.ShapefileDataStore; import org.geotools.data.shapefile.ShpFiles; import org.geotools.resources.NIOUtilities; /** * A DbaseFileReader is used to read a dbase III format file. <br> * The general use of this class is: <CODE><PRE> * FileChannel in = new FileInputStream("thefile.dbf").getChannel(); * DbaseFileReader r = new DbaseFileReader( in ) * Object[] fields = new Object[r.getHeader().getNumFields()]; * while (r.hasNext()) { * r.readEntry(fields); * // do stuff * } * r.close(); * </PRE></CODE> For consumers who wish to be a bit more selective with their reading * of rows, the Row object has been added. The semantics are the same as using * the readEntry method, but remember that the Row object is always the same. * The values are parsed as they are read, so it pays to copy them out (as each * call to Row.read() will result in an expensive String parse). <br> * <b>EACH CALL TO readEntry OR readRow ADVANCES THE FILE!</b><br> * An example of using the Row method of reading: <CODE><PRE> * FileChannel in = new FileInputStream("thefile.dbf").getChannel(); * DbaseFileReader r = new DbaseFileReader( in ) * int fields = r.getHeader().getNumFields(); * while (r.hasNext()) { * DbaseFileReader.Row row = r.readRow(); * for (int i = 0; i < fields; i++) { * // do stuff * Foo.bar( row.read(i) ); * } * } * r.close(); * </PRE></CODE> * * @author Ian Schneider * @author Tommaso Nolli * * @source $URL$ */ public class IndexedDbaseFileReader extends DbaseFileReader { public void goTo(int recno) throws IOException, UnsupportedOperationException { if (this.randomAccessEnabled) { long newPosition = this.header.getHeaderLength() + this.header.getRecordLength() * (long) (recno - 1); if (this.useMemoryMappedBuffer) { if(newPosition < this.currentOffset || (this.currentOffset + buffer.limit()) < (newPosition + header.getRecordLength())) { NIOUtilities.clean(buffer); FileChannel fc = (FileChannel) channel; if(fc.size() > newPosition + Integer.MAX_VALUE) { currentOffset = newPosition; } else { currentOffset = fc.size() - Integer.MAX_VALUE; } buffer = fc.map(MapMode.READ_ONLY, currentOffset, Integer.MAX_VALUE); buffer.position((int) (newPosition - currentOffset)); } else { buffer.position((int) (newPosition - currentOffset)); } } else { if (this.currentOffset <= newPosition && this.currentOffset + buffer.limit() >= newPosition) { buffer.position((int) (newPosition - this.currentOffset)); //System.out.println("Hit"); } else { //System.out.println("Jump"); FileChannel fc = (FileChannel) this.channel; fc.position(newPosition); this.currentOffset = newPosition; buffer.limit(buffer.capacity()); buffer.position(0); fill(buffer, fc); buffer.position(0); } } } else { throw new UnsupportedOperationException( "Random access not enabled!"); } } /** * Like calling DbaseFileReader(ReadableByteChannel, true); * * @param channel * @throws IOException */ public IndexedDbaseFileReader(ShpFiles shpFiles) throws IOException { this(shpFiles, false); } /** * Creates a new instance of DBaseFileReader * * @param channel * The readable channel to use. * @param useMemoryMappedBuffer * Wether or not map the file in memory * @throws IOException * If an error occurs while initializing. */ public IndexedDbaseFileReader(ShpFiles shpFiles, boolean useMemoryMappedBuffer) throws IOException { super(shpFiles, useMemoryMappedBuffer, ShapefileDataStore.DEFAULT_STRING_CHARSET, TimeZone.getDefault()); } public IndexedDbaseFileReader(ShpFiles shpFiles, boolean useMemoryMappedBuffer, Charset stringCharset) throws IOException { super(shpFiles, useMemoryMappedBuffer, stringCharset, TimeZone.getDefault()); } public IndexedDbaseFileReader(ShpFiles shpFiles, boolean useMemoryMappedBuffer, Charset stringCharset, TimeZone timeZone) throws IOException { super(shpFiles, useMemoryMappedBuffer, stringCharset, timeZone); } public boolean IsRandomAccessEnabled() { return this.randomAccessEnabled; } public static void main(String[] args) throws Exception { IndexedDbaseFileReader reader = new IndexedDbaseFileReader( new ShpFiles(args[0]), false); System.out.println(reader.getHeader()); int r = 0; while (reader.hasNext()) { System.out.println(++r + "," + java.util.Arrays.asList(reader.readEntry())); } reader.close(); } }