001: //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/trunk/src/org/deegree/io/shpapi/shape_new/ShapeFileWriter.java $
002: /*---------------- FILE HEADER ------------------------------------------
003: This file is part of deegree.
004: Copyright (C) 2001-2008 by:
005: Department of Geography, University of Bonn
006: http://www.giub.uni-bonn.de/deegree/
007: lat/lon GmbH
008: http://www.lat-lon.de
009:
010: This library is free software; you can redistribute it and/or
011: modify it under the terms of the GNU Lesser General Public
012: License as published by the Free Software Foundation; either
013: version 2.1 of the License, or (at your option) any later version.
014:
015: This library is distributed in the hope that it will be useful,
016: but WITHOUT ANY WARRANTY; without even the implied warranty of
017: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
018: Lesser General Public License for more details.
019:
020: You should have received a copy of the GNU Lesser General Public
021: License along with this library; if not, write to the Free Software
022: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
023:
024: Contact:
025:
026: Andreas Poth
027: lat/lon GmbH
028: Aennchenstr. 19
029: 53177 Bonn
030: Germany
031: E-Mail: poth@lat-lon.de
032:
033: Prof. Dr. Klaus Greve
034: Department of Geography
035: University of Bonn
036: Meckenheimer Allee 166
037: 53115 Bonn
038: Germany
039: E-Mail: greve@giub.uni-bonn.de
040:
041: ---------------------------------------------------------------------------*/
042: package org.deegree.io.shpapi.shape_new;
043:
044: import java.io.BufferedOutputStream;
045: import java.io.File;
046: import java.io.FileOutputStream;
047: import java.io.IOException;
048: import java.io.OutputStream;
049:
050: import org.deegree.framework.log.ILogger;
051: import org.deegree.framework.log.LoggerFactory;
052: import org.deegree.io.dbaseapi.DBaseException;
053: import org.deegree.model.spatialschema.ByteUtils;
054:
055: /**
056: * <code>ShapeFileWriter</code> is a class to write shapefiles.
057: *
058: * @author <a href="mailto:schmitz@lat-lon.de">Andreas Schmitz</a>
059: * @author last edited by: $Author: apoth $
060: *
061: * @version $Revision: 9342 $, $Date: 2007-12-27 04:32:57 -0800 (Thu, 27 Dec 2007) $
062: */
063: public class ShapeFileWriter {
064:
065: private ShapeFile shapeFile;
066:
067: private static final ILogger LOG = LoggerFactory
068: .getLogger(ShapeFileWriter.class);
069:
070: /**
071: * @param shapes
072: */
073: public ShapeFileWriter(ShapeFile shapes) {
074: shapeFile = shapes;
075: }
076:
077: private void writeHeader(OutputStream out, int length)
078: throws IOException {
079:
080: // what's funny about shapefiles:
081: // 1) in the headers, they use big endian for some values, little endian for others
082: // (the rest of the file is little endian)
083: // 2) Only 4 byte ints and 8 byte doubles are used in the file, however,
084: // the size is measured in 16 bit words...
085:
086: byte[] header = new byte[100];
087:
088: ByteUtils.writeBEInt(header, 0, ShapeFile.FILETYPE);
089: ByteUtils.writeBEInt(header, 24, length);
090: ByteUtils.writeLEInt(header, 28, ShapeFile.VERSION);
091: ByteUtils.writeLEInt(header, 32, shapeFile.getShapeType());
092:
093: ShapeEnvelope envelope = shapeFile.getEnvelope();
094: envelope.write(header, 36);
095:
096: // it shouldn't hurt to write these values as doubles default to 0.0 anyway
097: ByteUtils.writeLEDouble(header, 68, envelope.zmin);
098: ByteUtils.writeLEDouble(header, 76, envelope.zmax);
099: ByteUtils.writeLEDouble(header, 84, envelope.mmin);
100: ByteUtils.writeLEDouble(header, 92, envelope.mmax);
101:
102: out.write(header, 0, 100);
103: }
104:
105: private void writeShapes(OutputStream mainOut, OutputStream indexOut)
106: throws IOException {
107: // allocate the WHOLE shape file
108: byte[] bytes = new byte[shapeFile.getSize()];
109: byte[] indexBytes = new byte[8 * shapeFile.getShapes().size()];
110:
111: int recordNum = 1;
112: int offset = 0;
113: int indexOffset = 0;
114:
115: for (Shape s : shapeFile.getShapes()) {
116: ByteUtils.writeBEInt(indexBytes, indexOffset,
117: (100 + offset) / 2);
118: indexOffset += 4;
119: ByteUtils.writeBEInt(indexBytes, indexOffset, s
120: .getByteLength() / 2);
121: indexOffset += 4;
122:
123: ByteUtils.writeBEInt(bytes, offset, recordNum++);
124: offset += 4;
125: ByteUtils.writeBEInt(bytes, offset, s.getByteLength() / 2); // again 16-bit words
126: offset += 4;
127:
128: LOG.logDebug("Writing a " + s.getClass().getSimpleName()
129: + ", size " + s.getByteLength() + " from offset "
130: + offset);
131: offset = s.write(bytes, offset);
132: }
133:
134: mainOut.write(bytes, 0, bytes.length);
135: indexOut.write(indexBytes, 0, indexBytes.length);
136: }
137:
138: /**
139: * Writes the shapes to the files with the given base name.
140: *
141: * @param baseName
142: * @throws IOException
143: * @throws DBaseException
144: */
145: public void write(String baseName) throws IOException,
146: DBaseException {
147: File mainFile = new File(baseName + ".shp");
148: BufferedOutputStream mainOut = new BufferedOutputStream(
149: new FileOutputStream(mainFile));
150: writeHeader(mainOut, (shapeFile.getSize() + 100) / 2);
151:
152: File indexFile = new File(baseName + ".shx");
153: BufferedOutputStream indexOut = new BufferedOutputStream(
154: new FileOutputStream(indexFile));
155: writeHeader(indexOut,
156: (shapeFile.getShapes().size() * 8 + 100) / 2);
157:
158: writeShapes(mainOut, indexOut);
159:
160: mainOut.close();
161: indexOut.close();
162:
163: shapeFile.writeDBF();
164: }
165:
166: }
|