package jeql.io.shapefile; import java.io.BufferedOutputStream; import java.io.FileOutputStream; import java.io.IOException; import java.net.URL; import jeql.io.EndianDataOutputStream; import org.geotools.shapefile.PointHandler; import org.geotools.shapefile.ShapeHandler; import org.geotools.shapefile.ShapefileHeader; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.GeometryCollection; /** * Writes a list of geometries to a .shp file. * Requires all geometries to be resident in memory, * in order to write shp header at start of file. */ public class ShpWriter { private URL baseURL; /** * Creates a writer to the given url * @param url The url of the shapefile */ public ShpWriter(URL url) { baseURL = url; } private EndianDataOutputStream getOutputStream() throws IOException { BufferedOutputStream in = new BufferedOutputStream(new FileOutputStream( baseURL.getFile())); EndianDataOutputStream os = new EndianDataOutputStream(in); return os; } /** * Saves a shapefile to the output stream. * * @param coordDimension 2=x,y ; 3=x,y,m ; 4=x,y,z,m */ public void write(GeometryCollection geometries, int coordDimension) throws IOException, Exception { EndianDataOutputStream outStream = getOutputStream(); ShapefileHeader header = new ShapefileHeader(geometries, coordDimension); header.write(outStream); int pos = 50; // header length in WORDS //records; //body; //header; int numShapes = geometries.getNumGeometries(); ShapeHandler handler; if (geometries.getNumGeometries() == 0) { handler = new PointHandler(); //default } else { handler = Shapefile.getShapeHandler(geometries.getGeometryN(0), coordDimension); } for (int i = 0; i < numShapes; i++) { Geometry body = geometries.getGeometryN(i); outStream.writeIntBE(i + 1); outStream.writeIntBE(handler.getLength(body)); pos += 4; // length of header in WORDS handler.write(body, outStream); pos += handler.getLength(body); // length of shape in WORDS } outStream.flush(); outStream.close(); } //ShapeFileDimentions => 2=x,y ; 3=x,y,m ; 4=x,y,z,m public synchronized void writeIndex(GeometryCollection geometries, int coordDimension, String shxPath) throws IOException, Exception { Geometry geom; BufferedOutputStream in = new BufferedOutputStream(new FileOutputStream(shxPath)); EndianDataOutputStream outStream = new EndianDataOutputStream(in); ShapeHandler handler; int nrecords = geometries.getNumGeometries(); ShapefileHeader mainHeader = new ShapefileHeader(geometries, coordDimension); if (geometries.getNumGeometries() == 0) { handler = new PointHandler(); //default } else { handler = Shapefile.getShapeHandler(geometries.getGeometryN(0), coordDimension); } // mainHeader.fileLength = 50 + 4*nrecords; mainHeader.writeToIndex(outStream); int pos = 50; int len = 0; for (int i = 0; i < nrecords; i++) { geom = geometries.getGeometryN(i); len = handler.getLength(geom); outStream.writeIntBE(pos); outStream.writeIntBE(len); pos = pos + len + 4; } outStream.flush(); outStream.close(); } }