001 //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/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 13:32:57 +0100 (Do, 27 Dez 2007) $ 062 */ 063 public class ShapeFileWriter { 064 065 private ShapeFile shapeFile; 066 067 private static final ILogger LOG = LoggerFactory.getLogger( ShapeFileWriter.class ); 068 069 /** 070 * @param shapes 071 */ 072 public ShapeFileWriter( ShapeFile shapes ) { 073 shapeFile = shapes; 074 } 075 076 private void writeHeader( OutputStream out, int length ) 077 throws IOException { 078 079 // what's funny about shapefiles: 080 // 1) in the headers, they use big endian for some values, little endian for others 081 // (the rest of the file is little endian) 082 // 2) Only 4 byte ints and 8 byte doubles are used in the file, however, 083 // the size is measured in 16 bit words... 084 085 byte[] header = new byte[100]; 086 087 ByteUtils.writeBEInt( header, 0, ShapeFile.FILETYPE ); 088 ByteUtils.writeBEInt( header, 24, length ); 089 ByteUtils.writeLEInt( header, 28, ShapeFile.VERSION ); 090 ByteUtils.writeLEInt( header, 32, shapeFile.getShapeType() ); 091 092 ShapeEnvelope envelope = shapeFile.getEnvelope(); 093 envelope.write( header, 36 ); 094 095 // it shouldn't hurt to write these values as doubles default to 0.0 anyway 096 ByteUtils.writeLEDouble( header, 68, envelope.zmin ); 097 ByteUtils.writeLEDouble( header, 76, envelope.zmax ); 098 ByteUtils.writeLEDouble( header, 84, envelope.mmin ); 099 ByteUtils.writeLEDouble( header, 92, envelope.mmax ); 100 101 out.write( header, 0, 100 ); 102 } 103 104 private void writeShapes( OutputStream mainOut, OutputStream indexOut ) 105 throws IOException { 106 // allocate the WHOLE shape file 107 byte[] bytes = new byte[shapeFile.getSize()]; 108 byte[] indexBytes = new byte[8 * shapeFile.getShapes().size()]; 109 110 int recordNum = 1; 111 int offset = 0; 112 int indexOffset = 0; 113 114 for ( Shape s : shapeFile.getShapes() ) { 115 ByteUtils.writeBEInt( indexBytes, indexOffset, ( 100 + offset ) / 2 ); 116 indexOffset += 4; 117 ByteUtils.writeBEInt( indexBytes, indexOffset, s.getByteLength() / 2 ); 118 indexOffset += 4; 119 120 ByteUtils.writeBEInt( bytes, offset, recordNum++ ); 121 offset += 4; 122 ByteUtils.writeBEInt( bytes, offset, s.getByteLength() / 2 ); // again 16-bit words 123 offset += 4; 124 125 LOG.logDebug( "Writing a " + s.getClass().getSimpleName() + ", size " + s.getByteLength() + " from offset " + offset ); 126 offset = s.write( bytes, offset ); 127 } 128 129 mainOut.write( bytes, 0, bytes.length ); 130 indexOut.write( indexBytes, 0, indexBytes.length ); 131 } 132 133 /** 134 * Writes the shapes to the files with the given base name. 135 * 136 * @param baseName 137 * @throws IOException 138 * @throws DBaseException 139 */ 140 public void write( String baseName ) 141 throws IOException, DBaseException { 142 File mainFile = new File( baseName + ".shp" ); 143 BufferedOutputStream mainOut = new BufferedOutputStream( new FileOutputStream( mainFile ) ); 144 writeHeader( mainOut, ( shapeFile.getSize() + 100 ) / 2 ); 145 146 File indexFile = new File( baseName + ".shx" ); 147 BufferedOutputStream indexOut = new BufferedOutputStream( new FileOutputStream( indexFile ) ); 148 writeHeader( indexOut, ( shapeFile.getShapes().size() * 8 + 100 ) / 2 ); 149 150 writeShapes( mainOut, indexOut ); 151 152 mainOut.close(); 153 indexOut.close(); 154 155 shapeFile.writeDBF(); 156 } 157 158 }