Statistics
| Revision:

root / branches / v10 / libraries / libFMap / src / com / iver / cit / gvsig / fmap / drivers / shp / DbaseFileNIO.java @ 11674

History | View | Annotate | Download (11.3 KB)

1 1100 fjp
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
 *
3
 * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
4
 *
5
 * This program is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License
7
 * as published by the Free Software Foundation; either version 2
8
 * of the License, or (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
18
 *
19
 * For more information, contact:
20
 *
21
 *  Generalitat Valenciana
22
 *   Conselleria d'Infraestructures i Transport
23
 *   Av. Blasco Ib??ez, 50
24
 *   46010 VALENCIA
25
 *   SPAIN
26
 *
27
 *      +34 963862235
28
 *   gvsig@gva.es
29
 *      www.gvsig.gva.es
30
 *
31
 *    or
32
 *
33
 *   IVER T.I. S.A
34
 *   Salamanca 50
35
 *   46005 Valencia
36
 *   Spain
37
 *
38
 *   +34 963163400
39
 *   dac@iver.es
40
 */
41 377 fjp
package com.iver.cit.gvsig.fmap.drivers.shp;
42
43
import java.io.File;
44
import java.io.FileInputStream;
45
import java.io.IOException;
46 6926 fjp
import java.io.UnsupportedEncodingException;
47 377 fjp
import java.nio.ByteBuffer;
48 6926 fjp
import java.nio.CharBuffer;
49 377 fjp
import java.nio.channels.FileChannel;
50 6926 fjp
import java.nio.charset.Charset;
51
import java.nio.charset.CharsetDecoder;
52 377 fjp
53 4430 fjp
import com.iver.utiles.bigfile.BigByteBuffer2;
54 377 fjp
55 2632 fjp
56 377 fjp
/**
57
 * Class to read and write data to a dbase III format file. Creation date:
58
 * (5/15/2001 5:15:13 PM)
59
 */
60
public class DbaseFileNIO {
61 1005 vcaballero
        // Header information for the DBase File
62
        private DbaseFileHeaderNIO myHeader;
63
        private FileInputStream fin;
64
        private FileChannel channel;
65 4430 fjp
        private BigByteBuffer2 buffer;
66 6926 fjp
67
        CharBuffer charBuffer;
68
          CharsetDecoder decoder;
69
          Charset chars;
70
71 377 fjp
72 1005 vcaballero
        /**
73
         * Retrieve number of records in the DbaseFile
74
         *
75
         * @return N?mero de registros.
76
         */
77
        public int getRecordCount() {
78
                return myHeader.getNumRecords();
79
        }
80 377 fjp
81 1005 vcaballero
        /**
82
         * Devuelve el n?mero de fields.
83
         *
84
         * @return N?mero de fields.
85
         */
86
        public int getFieldCount() {
87
                return myHeader.getNumFields();
88
        }
89 377 fjp
90 1005 vcaballero
        /**
91
         * Devuelve el valor de un boolean a partir de su n?mero de fila y de
92
         * field.
93
         *
94
         * @param rowIndex N?mero de fila.
95
         * @param fieldId N?mero columna.
96
         *
97
         * @return boolean.
98
         */
99
        public boolean getBooleanFieldValue(int rowIndex, int fieldId) {
100
                int recordOffset = (myHeader.getRecordLength() * rowIndex) +
101
                        myHeader.getHeaderLength() + 1;
102 377 fjp
103
                //Se calcula el offset del campo
104
                int fieldOffset = 0;
105 1005 vcaballero
106
                for (int i = 0; i < (fieldId - 1); i++) {
107 377 fjp
                        fieldOffset += myHeader.getFieldLength(i);
108
                }
109 1005 vcaballero
110 377 fjp
                buffer.position(recordOffset + fieldOffset);
111 1005 vcaballero
112 377 fjp
                char bool = (char) buffer.get();
113 1005 vcaballero
114
                return ((bool == 't') || (bool == 'T') || (bool == 'Y') ||
115
                (bool == 'y'));
116 377 fjp
        }
117
118 1005 vcaballero
        /**
119
         * Devuelve el String a partir del n?mero de fila y columna.
120
         *
121
         * @param rowIndex N?mero de fila.
122
         * @param fieldId N?mero de columna.
123
         *
124
         * @return String.
125 6926 fjp
         * @throws UnsupportedEncodingException
126 1005 vcaballero
         */
127 6926 fjp
        public String getStringFieldValue(int rowIndex, int fieldId) throws UnsupportedEncodingException {
128 377 fjp
                int recordOffset = (myHeader.getRecordLength() * rowIndex) +
129 1005 vcaballero
                        myHeader.getHeaderLength() + 1;
130
131 377 fjp
                //Se calcula el offset del campo
132
                int fieldOffset = 0;
133 1005 vcaballero
134
                for (int i = 0; i < fieldId; i++) {
135 377 fjp
                        fieldOffset += myHeader.getFieldLength(i);
136
                }
137 1005 vcaballero
138 377 fjp
                buffer.position(recordOffset + fieldOffset);
139 1005 vcaballero
140 377 fjp
                byte[] data = new byte[myHeader.getFieldLength(fieldId)];
141 6926 fjp
142
//                ByteBuffer byteBuffer = ByteBuffer.wrap(data);
143
144
145 377 fjp
                buffer.get(data);
146 6926 fjp
                return new String(data, chars.name());
147 377 fjp
        }
148 1005 vcaballero
149
        /**
150
         * Devuelve el Number a partir de una fila y columna.
151
         *
152
         * @param rowIndex N?mero fila.
153
         * @param fieldId N?mero columna.
154
         *
155
         * @return Number.
156
         */
157
        public Number getNumberFieldValue(int rowIndex, int fieldId) {
158 377 fjp
                //System.out.println("rowIndex = "+rowIndex+ " , "+"fieldId = "+fieldId);
159
                int recordOffset = (myHeader.getRecordLength() * rowIndex) +
160 1005 vcaballero
                        myHeader.getHeaderLength() + 1;
161
162 377 fjp
                //Se calcula el offset del campo
163
                int fieldOffset = 0;
164 1005 vcaballero
165
                for (int i = 0; i < fieldId; i++) {
166 377 fjp
                        fieldOffset += myHeader.getFieldLength(i);
167
                }
168 1005 vcaballero
169 377 fjp
                buffer.position(recordOffset + fieldOffset);
170 1005 vcaballero
171 377 fjp
                byte[] data = new byte[myHeader.getFieldLength(fieldId)];
172
                buffer.get(data);
173 1005 vcaballero
174
                String s = new String(data);
175
                s = s.trim();
176
177
                if (getFieldType(fieldId) == 'N') {
178 377 fjp
                        Object tempObject = Double.valueOf(s);
179 1005 vcaballero
180
                        return new Double(tempObject.toString());
181
                } else {
182 377 fjp
                        Object tempObject = Integer.valueOf(s);
183 1005 vcaballero
184
                        return new Integer(tempObject.toString());
185 377 fjp
                }
186 1005 vcaballero
187 377 fjp
                //return 0;
188
        }
189
190 1005 vcaballero
        // Retrieve the record at the given index
191 377 fjp
192 1005 vcaballero
        /*    public Object[] getRecord(long inIndex) throws IOException {
193
           long nRecordOffset = (myHeader.getRecordLength() * inIndex) +
194
               myHeader.getHeaderLength();
195
           // retrieve the record length
196
           int tempNumFields = myHeader.getNumFields();
197
           // storage for the actual values
198
           Object[] tempRow = new Object[tempNumFields];
199
               buffer.position((int) nRecordOffset);
200
               // read the deleted flag
201
               char tempDeleted = (char) buffer.get();
202
               // read the record length
203
               int tempRecordLength = 1; // for the deleted character just read.
204
               // read the Fields
205
               for (int j = 0; j < tempNumFields; j++) {
206
                   // find the length of the field.
207
                   int tempFieldLength = myHeader.getFieldLength(j);
208
                   tempRecordLength = tempRecordLength + tempFieldLength;
209
                   // find the field type
210
                   char tempFieldType = myHeader.getFieldType(j);
211
                   //System.out.print("Reading Name="+myHeader.getFieldName(j)+" Type="+tempFieldType +" Length="+tempFieldLength);
212
                   // read the data.
213
                   Object tempObject = null;
214
                   switch (tempFieldType) {
215
                   case 'L': // logical data type, one character (T,t,F,f,Y,y,N,n)
216
                       char tempChar = (char) buffer.get();
217
                       if ((tempChar == 'T') || (tempChar == 't') ||
218
                               (tempChar == 'Y') || (tempChar == 'y')) {
219
                           tempObject = new Boolean(true);
220
                       } else {
221
                           tempObject = new Boolean(false);
222
                       }
223
                       break;
224
                   case 'C': // character record.
225
                       byte[] sbuffer = new byte[tempFieldLength];
226
                                           buffer.get(sbuffer);
227
                       tempObject = new String(sbuffer, "ISO-8859-1").trim();
228
                       break;
229
                   case 'D': // date data type.
230
                       byte[] dbuffer = new byte[8];
231
                                           buffer.get(dbuffer);
232
                       String tempString = new String(dbuffer, 0, 4);
233
                       try {
234
                           int tempYear = Integer.parseInt(tempString);
235
                           tempString = new String(dbuffer, 4, 2);
236
                           int tempMonth = Integer.parseInt(tempString) - 1;
237
                           tempString = new String(dbuffer, 6, 2);
238
                           int tempDay = Integer.parseInt(tempString);
239
                           Calendar c = Calendar.getInstance();
240
                           c.set(Calendar.YEAR, tempYear);
241
                           c.set(Calendar.MONTH, tempMonth);
242
                           c.set(Calendar.DAY_OF_MONTH, tempDay);
243
                           tempObject = c.getTime();
244
                       } catch (NumberFormatException e) {
245
                       }
246
                       break;
247
                   case 'M': // memo field.
248
                       byte[] mbuffer = new byte[10];
249
                                           buffer.get(mbuffer);
250
                       break;
251
                   case 'N': // number
252
                   case 'F': // floating point number
253
                       byte[] fbuffer = new byte[tempFieldLength];
254
                                           buffer.get(fbuffer);
255
                       try {
256
                           tempString = new String(fbuffer);
257
                           tempObject = Double.valueOf(tempString.trim());
258
                       } catch (NumberFormatException e) {
259
                       }
260
                       break;
261
                   default:
262
                       byte[] defbuffer = new byte[tempFieldLength];
263
                                           buffer.get(defbuffer);
264
                       System.out.println("Do not know how to parse Field type " +
265
                           tempFieldType);
266
                   }
267
                   tempRow[j] = tempObject;
268
                   //                                System.out.println(" Data="+tempObject);
269
               }
270
               // ensure that the full record has been read.
271
               if (tempRecordLength < myHeader.getRecordLength()) {
272
                   byte[] tempbuff = new byte[myHeader.getRecordLength() -
273
                       tempRecordLength];
274
                   buffer.get(tempbuff);
275
                   /* if (tempTelling){
276
                           System.out.println("DBF File has "+(myHeader.getRecordLength()-tempRecordLength)+" extra bytes per record");
277
                           tempTelling = false;
278
                   } */
279
        /*           }
280
           return tempRow;
281
           }
282
         */
283 377 fjp
284 1005 vcaballero
        /**
285
         * Retrieve the name of the given column.
286
         *
287
         * @param inIndex ?ndice.
288
         *
289
         * @return nombre del campo.
290
         */
291
        public String getFieldName(int inIndex) {
292
                return myHeader.getFieldName(inIndex).trim();
293
        }
294 377 fjp
295 1005 vcaballero
        /**
296
         * Retrieve the type of the given column.
297
         *
298
         * @param inIndex ?ndice.
299
         *
300
         * @return tipo de campo.
301
         */
302
        public char getFieldType(int inIndex) {
303
                return myHeader.getFieldType(inIndex);
304
        }
305 377 fjp
306 1005 vcaballero
        /**
307
         * Retrieve the length of the given column.
308
         *
309
         * @param inIndex indice.
310
         *
311
         * @return longitud del field.
312
         */
313
        public int getFieldLength(int inIndex) {
314
                return myHeader.getFieldLength(inIndex);
315
        }
316 377 fjp
317 1005 vcaballero
        /*
318
         * Retrieve the value of the given column as string.
319
         *
320
         * @param idField DOCUMENT ME!
321
         * @param idRecord DOCUMENT ME!
322
         *
323
         * @return DOCUMENT ME!
324
         *
325
                 public Object getFieldValue(int idField, long idRecord) throws IOException {
326
                     Object[] tmpReg = getRecord(idRecord);
327
                     return tmpReg[idField];
328
                 }
329
         */
330
        /*
331
         * DOCUMENT ME!
332
         *
333
         * @param idField DOCUMENT ME!
334
         * @param idRecord DOCUMENT ME!
335
         *
336
         * @return DOCUMENT ME!
337
         *
338
                 public double getFieldValueAsDouble(int idField, int idRecord) throws IOException {
339
                     Object[] tmpReg = getRecord(idRecord);
340
                     return (double) Double.parseDouble(tmpReg[idField].toString());
341
                 }
342
         */
343 377 fjp
344 1005 vcaballero
        /**
345
         * Retrieve the location of the decimal point.
346
         *
347
         * @param inIndex ?ndice.
348
         *
349
         * @return localizaci?n.
350
         */
351
        public int getFieldDecimalLength(int inIndex) {
352
                return myHeader.getFieldDecimalCount(inIndex);
353
        }
354 377 fjp
355 1005 vcaballero
        /**
356
         * read the DBF file into memory.
357
         *
358
         * @param file Fichero.
359
         *
360
         * @throws IOException
361
         */
362
        public void open(File file) throws IOException {
363
                fin = new FileInputStream(file);
364
                channel = fin.getChannel();
365 377 fjp
366 2632 fjp
        // buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());
367 4430 fjp
        buffer = new BigByteBuffer2(channel, FileChannel.MapMode.READ_ONLY);
368 377 fjp
369 1005 vcaballero
                // create the header to contain the header information.
370
                myHeader = new DbaseFileHeaderNIO();
371
                myHeader.readHeader(buffer);
372 6926 fjp
373
                charBuffer = CharBuffer.allocate(myHeader.getRecordLength() - 1);
374
                chars = Charset.forName("ISO-8859-1");
375
                decoder = chars.newDecoder();
376
377 1005 vcaballero
        }
378 377 fjp
379 1005 vcaballero
        /**
380
         * Removes all data from the dataset
381
         *
382
         * @throws IOException .
383
         */
384
        public void close() throws IOException {
385
                fin.close();
386 377 fjp
                channel.close();
387 1005 vcaballero
        }
388 4430 fjp
389
        /**
390
         * @return Returns the DbaseFileHeaderNIO.
391
         */
392
        public DbaseFileHeaderNIO getDBaseHeader() {
393
                return myHeader;
394
        }
395 377 fjp
}