package jeql.io.shapefile; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import jeql.io.EndianDataOutputStream; import org.geotools.shapefile.PointHandler; import org.geotools.shapefile.ShapeHandler; import org.geotools.shapefile.Shapefile; import org.geotools.shapefile.ShapefileHeader; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.GeometryCollection; /** * Writes a shapefile in a streaming fashion. * * NOT COMPLETE Need to deal with requirement to write length and BBox in * header! * * @author Martin Davis * */ public class ShapefileStreamWriter { EndianDataOutputStream outStream = null; File file; public ShapefileStreamWriter(String filename) { file = new File(filename); } private EndianDataOutputStream getOutputStream(File file) throws IOException { BufferedOutputStream in = new BufferedOutputStream(new FileOutputStream( file)); EndianDataOutputStream sfile = new EndianDataOutputStream(in); return sfile; } private EndianDataOutputStream getOutStream() throws IOException { if (outStream == null) { outStream = getOutputStream(file); } return outStream; } public void write(GeometryCollection geometries, int shapeFileDimension) throws IOException, Exception { EndianDataOutputStream file = getOutStream(); ShapefileHeader mainHeader = new ShapefileHeader(geometries, shapeFileDimension); mainHeader.write(file); int pos = 50; // header length in WORDS // records; // body; // header; int numShapes = geometries.getNumGeometries(); Geometry body; ShapeHandler handler; if (geometries.getNumGeometries() == 0) { handler = new PointHandler(); // default } else { handler = Shapefile.getShapeHandler(geometries.getGeometryN(0), shapeFileDimension); } for (int i = 0; i < numShapes; i++) { body = geometries.getGeometryN(i); file.writeIntBE(i + 1); file.writeIntBE(handler.getLength(body)); pos += 4; // length of header in WORDS handler.write(body, file); pos += handler.getLength(body); // length of shape in WORDS } file.flush(); file.close(); } // ShapeFileDimentions => 2=x,y ; 3=x,y,m ; 4=x,y,z,m public synchronized void writeIndex(GeometryCollection geometries, EndianDataOutputStream file, int ShapeFileDimentions) throws IOException, Exception { Geometry geom; ShapeHandler handler; int nrecords = geometries.getNumGeometries(); ShapefileHeader mainHeader = new ShapefileHeader(geometries, ShapeFileDimentions); if (geometries.getNumGeometries() == 0) { handler = new PointHandler(); // default } else { handler = Shapefile.getShapeHandler(geometries.getGeometryN(0), ShapeFileDimentions); } // mainHeader.fileLength = 50 + 4*nrecords; mainHeader.writeToIndex(file); int pos = 50; int len = 0; // file.setLittleEndianMode(false); for (int i = 0; i < nrecords; i++) { geom = geometries.getGeometryN(i); len = handler.getLength(geom); file.writeIntBE(pos); file.writeIntBE(len); pos = pos + len + 4; } file.flush(); file.close(); } }