001 //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_testing/src/org/deegree/io/shpapi/FileHeader.java $
002
003 /*----------------------------------------------------------------------------
004 This file is part of deegree, http://deegree.org/
005 Copyright (C) 2001-2009 by:
006 Department of Geography, University of Bonn
007 and
008 lat/lon GmbH
009
010 This library is free software; you can redistribute it and/or modify it under
011 the terms of the GNU Lesser General Public License as published by the Free
012 Software Foundation; either version 2.1 of the License, or (at your option)
013 any later version.
014 This library is distributed in the hope that it will be useful, but WITHOUT
015 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
016 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
017 details.
018 You should have received a copy of the GNU Lesser General Public License
019 along with this library; if not, write to the Free Software Foundation, Inc.,
020 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
021
022 Contact information:
023
024 lat/lon GmbH
025 Aennchenstr. 19, 53177 Bonn
026 Germany
027 http://lat-lon.de/
028
029 Department of Geography, University of Bonn
030 Prof. Dr. Klaus Greve
031 Postfach 1147, 53001 Bonn
032 Germany
033 http://www.geographie.uni-bonn.de/deegree/
034
035 e-mail: info@deegree.org
036 ----------------------------------------------------------------------------*/
037
038 package org.deegree.io.shpapi;
039
040 import java.io.IOException;
041 import java.io.RandomAccessFile;
042
043 import org.deegree.model.spatialschema.ByteUtils;
044
045 /**
046 * Class representing an ESRI Index File Header.
047 * <p>
048 * Uses class ByteUtils ShapeUtils modified from the original package com.bbn.openmap.layer.shape
049 * <br>
050 * Copyright (C) 1998 BBN Corporation 10 Moulton St. Cambridge, MA 02138 <br>
051 *
052 * @version 16.08.2000
053 * @author Andreas Poth
054 *
055 */
056
057 public class FileHeader {
058
059 /*
060 * The buffer that holds the 100 byte header.
061 */
062 private byte[] header;
063
064 /*
065 * Holds the length of the file, in bytes.
066 */
067 private long fileLength;
068
069 /*
070 * Holds the version of the file, as an int.
071 */
072 private int fileVersion;
073
074 /*
075 * Holds the shape type of the file.
076 */
077 private int fileShapeType;
078
079 /*
080 * Holds the bounds of the file (four pairs of doubles).
081 */
082 private SHPEnvelope fileMBR;
083
084 /*
085 * local copy of the index-file randomaccess variable;
086 */
087 private RandomAccessFile rafShp = null;
088
089 /**
090 * Construct a IndexFileHeader from a file name.
091 *
092 * @param rafShp_
093 * @throws IOException
094 */
095 public FileHeader( RandomAccessFile rafShp_ ) throws IOException {
096
097 rafShp = rafShp_;
098
099 initHeader( false );
100 }
101
102 /**
103 * Construct a IndexFileHeader from a file name.
104 *
105 * @param rafShp_
106 * @param newHeader
107 * @throws IOException
108 */
109 public FileHeader( RandomAccessFile rafShp_, boolean newHeader ) throws IOException {
110
111 rafShp = rafShp_;
112
113 initHeader( newHeader );
114 }
115
116 /**
117 * method: getFileMBR();<BR>
118 * Returns the bounding box of this shape file. The bounding box<BR>
119 * is the smallest rectangle that encloses all the shapes in the<BR>
120 * file.<BR>
121 *
122 * @return the bounding box of this shape file. The bounding box<BR>
123 * is the smallest rectangle that encloses all the shapes in the<BR>
124 * file.<BR>
125 */
126
127 public SHPEnvelope getFileMBR() {
128
129 return fileMBR;
130
131 }
132
133 /**
134 * method: getFileLength()<BR>
135 * returns the length of the shape file in bytes<BR>
136 *
137 * @return the length of the shape file in bytes<BR>
138 */
139 public long getFileLength() {
140
141 return fileLength;
142
143 }
144
145 /**
146 * method: getFileVersion()<BR>
147 * returns the version of the shape file<BR>
148 *
149 * @return the version of the shape file<BR>
150 */
151 public int getFileVersion() {
152
153 return fileVersion;
154
155 }
156
157 /**
158 * method: getFileShapeType()<BR>
159 * returns the code for the shape type of the file<BR>
160 *
161 * @return the code for the shape type of the file<BR>
162 */
163 public int getFileShapeType() {
164 return fileShapeType;
165 }
166
167 /**
168 * Reads the header of a Shape file. If the file<BR>
169 * is empty, a blank header is written and then read. If the<BR>
170 * file is not empty, the header is read.<BR>
171 * After this function runs, the file pointer is set to byte 100,<BR>
172 * the first byte of the first record in the file.<BR>
173 */
174
175 private void initHeader( boolean newHeader )
176 throws IOException {
177
178 if ( newHeader )
179 writeHeader();
180 /*
181 * if (rafShp.read() == -1) { //File is empty, write a new one (what else???) writeHeader(); }
182 */
183 readHeader();
184 }
185
186 /**
187 * method: writeHeader()<BR>
188 * Writes a blank header into the shape file.<BR>
189 *
190 * @throws IOException
191 */
192 public void writeHeader()
193 throws IOException {
194
195 header = new byte[ShapeConst.SHAPE_FILE_HEADER_LENGTH];
196
197 ByteUtils.writeBEInt( header, 0, ShapeConst.SHAPE_FILE_CODE );
198 ByteUtils.writeBEInt( header, 24, 50 );
199
200 // empty shape file size in 16 bit words
201 ByteUtils.writeLEInt( header, 28, ShapeConst.SHAPE_FILE_VERSION );
202 ByteUtils.writeLEInt( header, 32, ShapeConst.SHAPE_TYPE_NULL );
203 ByteUtils.writeLEDouble( header, 36, 0.0 );
204 ByteUtils.writeLEDouble( header, 44, 0.0 );
205 ByteUtils.writeLEDouble( header, 52, 0.0 );
206 ByteUtils.writeLEDouble( header, 60, 0.0 );
207
208 rafShp.seek( 0 );
209 rafShp.write( header, 0, ShapeConst.SHAPE_FILE_HEADER_LENGTH );
210
211 }
212
213 /**
214 * method: writeHeader(int filelength, byte shptype,SHPEnvelope mbr)<BR>
215 * Writes a header into the shape file.<BR>
216 *
217 * @param filelength
218 * @param shptype
219 * @param mbr
220 * @throws IOException
221 */
222 public void writeHeader( int filelength, int shptype, SHPEnvelope mbr )
223 throws IOException {
224
225 header = new byte[ShapeConst.SHAPE_FILE_HEADER_LENGTH];
226
227 ByteUtils.writeBEInt( header, 0, ShapeConst.SHAPE_FILE_CODE );
228 ByteUtils.writeBEInt( header, 24, filelength / 2 );
229 ByteUtils.writeLEInt( header, 28, ShapeConst.SHAPE_FILE_VERSION );
230 ByteUtils.writeLEInt( header, 32, shptype );
231 ShapeUtils.writeBox( header, 36, mbr );
232
233 rafShp.seek( 0 );
234 rafShp.write( header, 0, ShapeConst.SHAPE_FILE_HEADER_LENGTH );
235 }
236
237 /**
238 * Reads and parses the header of the file. Values from the header<BR>
239 * are stored in the fields of this class.<BR>
240 */
241 private void readHeader()
242 throws IOException {
243
244 header = new byte[ShapeConst.SHAPE_FILE_HEADER_LENGTH];
245
246 /*
247 * Make sure we're at the beginning of the file
248 */
249 rafShp.seek( 0 );
250
251 rafShp.read( header, 0, ShapeConst.SHAPE_FILE_HEADER_LENGTH );
252
253 int fileCode = ByteUtils.readBEInt( header, 0 );
254
255 if ( fileCode != ShapeConst.SHAPE_FILE_CODE ) {
256
257 throw new IOException( "Invalid file code, " + "probably not a shape file" );
258
259 }
260
261 fileVersion = ByteUtils.readLEInt( header, 28 );
262
263 if ( fileVersion != ShapeConst.SHAPE_FILE_VERSION ) {
264
265 throw new IOException( "Unable to read shape files with version " + fileVersion );
266
267 }
268
269 fileLength = ByteUtils.readBEInt( header, 24 );
270
271 /*
272 * convert from 16-bit words to 8-bit bytes
273 */
274 fileLength *= 2;
275
276 fileShapeType = ByteUtils.readLEInt( header, 32 );
277
278 /*
279 * read ESRIBoundingBox and convert to SHPEnvelope
280 */
281 fileMBR = new SHPEnvelope( ShapeUtils.readBox( header, 36 ) );
282
283 }
284
285 }