Statistics
| Revision:

root / trunk / libraries / libFMap / src / com / iver / cit / gvsig / fmap / drivers / shp / DbaseFileNIO.java @ 10627

History | View | Annotate | Download (11.3 KB)

1
/* 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
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
import java.io.UnsupportedEncodingException;
47
import java.nio.CharBuffer;
48
import java.nio.channels.FileChannel;
49
import java.nio.charset.Charset;
50
import java.nio.charset.CharsetDecoder;
51

    
52
import com.iver.utiles.bigfile.BigByteBuffer2;
53

    
54

    
55
/**
56
 * Class to read and write data to a dbase III format file. Creation date:
57
 * (5/15/2001 5:15:13 PM)
58
 */
59
public class DbaseFileNIO {
60
        // Header information for the DBase File
61
        private DbaseFileHeaderNIO myHeader;
62
        private FileInputStream fin;
63
        private FileChannel channel;
64
        private BigByteBuffer2 buffer;
65
        
66
        CharBuffer charBuffer;
67
          CharsetDecoder decoder;
68
          Charset chars;
69
        
70

    
71
        /**
72
         * Retrieve number of records in the DbaseFile
73
         *
74
         * @return N?mero de registros.
75
         */
76
        public int getRecordCount() {
77
                return myHeader.getNumRecords();
78
        }
79

    
80
        /**
81
         * Devuelve el n?mero de fields.
82
         *
83
         * @return N?mero de fields.
84
         */
85
        public int getFieldCount() {
86
                return myHeader.getNumFields();
87
        }
88

    
89
        /**
90
         * Devuelve el valor de un boolean a partir de su n?mero de fila y de
91
         * field.
92
         *
93
         * @param rowIndex N?mero de fila.
94
         * @param fieldId N?mero columna.
95
         *
96
         * @return boolean.
97
         */
98
        public boolean getBooleanFieldValue(int rowIndex, int fieldId) {
99
                int recordOffset = (myHeader.getRecordLength() * rowIndex) +
100
                        myHeader.getHeaderLength() + 1;
101

    
102
                //Se calcula el offset del campo
103
                int fieldOffset = 0;
104

    
105
                for (int i = 0; i < (fieldId - 1); i++) {
106
                        fieldOffset += myHeader.getFieldLength(i);
107
                }
108

    
109
                buffer.position(recordOffset + fieldOffset);
110

    
111
                char bool = (char) buffer.get();
112

    
113
                return ((bool == 't') || (bool == 'T') || (bool == 'Y') ||
114
                (bool == 'y'));
115
        }
116

    
117
        /**
118
         * Devuelve el String a partir del n?mero de fila y columna.
119
         *
120
         * @param rowIndex N?mero de fila.
121
         * @param fieldId N?mero de columna.
122
         *
123
         * @return String.
124
         * @throws UnsupportedEncodingException 
125
         */
126
        public String getStringFieldValue(int rowIndex, int fieldId) throws UnsupportedEncodingException {
127
                int recordOffset = (myHeader.getRecordLength() * rowIndex) +
128
                        myHeader.getHeaderLength() + 1;
129

    
130
                //Se calcula el offset del campo
131
                int fieldOffset = 0;
132

    
133
                for (int i = 0; i < fieldId; i++) {
134
                        fieldOffset += myHeader.getFieldLength(i);
135
                }
136

    
137
                buffer.position(recordOffset + fieldOffset);
138

    
139
                byte[] data = new byte[myHeader.getFieldLength(fieldId)];
140

    
141
//                ByteBuffer byteBuffer = ByteBuffer.wrap(data);
142
                
143
                
144
                buffer.get(data);
145
                return new String(data, chars.name());
146
        }
147

    
148
        /**
149
         * Devuelve el Number a partir de una fila y columna.
150
         *
151
         * @param rowIndex N?mero fila.
152
         * @param fieldId N?mero columna.
153
         *
154
         * @return Number.
155
         */
156
        public Number getNumberFieldValue(int rowIndex, int fieldId) {
157
                //System.out.println("rowIndex = "+rowIndex+ " , "+"fieldId = "+fieldId);
158
                int recordOffset = (myHeader.getRecordLength() * rowIndex) +
159
                        myHeader.getHeaderLength() + 1;
160

    
161
                //Se calcula el offset del campo
162
                int fieldOffset = 0;
163

    
164
                for (int i = 0; i < fieldId; i++) {
165
                        fieldOffset += myHeader.getFieldLength(i);
166
                }
167

    
168
                buffer.position(recordOffset + fieldOffset);
169

    
170
                byte[] data = new byte[myHeader.getFieldLength(fieldId)];
171
                buffer.get(data);
172

    
173
                String s = new String(data);
174
                s = s.trim();
175

    
176
                if (getFieldType(fieldId) == 'N') {
177
                        Object tempObject = Double.valueOf(s);
178

    
179
                        return new Double(tempObject.toString());
180
                } else {
181
                        Object tempObject = Integer.valueOf(s);
182

    
183
                        return new Integer(tempObject.toString());
184
                }
185

    
186
                //return 0;
187
        }
188

    
189
        // Retrieve the record at the given index
190

    
191
        /*    public Object[] getRecord(long inIndex) throws IOException {
192
           long nRecordOffset = (myHeader.getRecordLength() * inIndex) +
193
               myHeader.getHeaderLength();
194
           // retrieve the record length
195
           int tempNumFields = myHeader.getNumFields();
196
           // storage for the actual values
197
           Object[] tempRow = new Object[tempNumFields];
198
               buffer.position((int) nRecordOffset);
199
               // read the deleted flag
200
               char tempDeleted = (char) buffer.get();
201
               // read the record length
202
               int tempRecordLength = 1; // for the deleted character just read.
203
               // read the Fields
204
               for (int j = 0; j < tempNumFields; j++) {
205
                   // find the length of the field.
206
                   int tempFieldLength = myHeader.getFieldLength(j);
207
                   tempRecordLength = tempRecordLength + tempFieldLength;
208
                   // find the field type
209
                   char tempFieldType = myHeader.getFieldType(j);
210
                   //System.out.print("Reading Name="+myHeader.getFieldName(j)+" Type="+tempFieldType +" Length="+tempFieldLength);
211
                   // read the data.
212
                   Object tempObject = null;
213
                   switch (tempFieldType) {
214
                   case 'L': // logical data type, one character (T,t,F,f,Y,y,N,n)
215
                       char tempChar = (char) buffer.get();
216
                       if ((tempChar == 'T') || (tempChar == 't') ||
217
                               (tempChar == 'Y') || (tempChar == 'y')) {
218
                           tempObject = new Boolean(true);
219
                       } else {
220
                           tempObject = new Boolean(false);
221
                       }
222
                       break;
223
                   case 'C': // character record.
224
                       byte[] sbuffer = new byte[tempFieldLength];
225
                                           buffer.get(sbuffer);
226
                       tempObject = new String(sbuffer, "ISO-8859-1").trim();
227
                       break;
228
                   case 'D': // date data type.
229
                       byte[] dbuffer = new byte[8];
230
                                           buffer.get(dbuffer);
231
                       String tempString = new String(dbuffer, 0, 4);
232
                       try {
233
                           int tempYear = Integer.parseInt(tempString);
234
                           tempString = new String(dbuffer, 4, 2);
235
                           int tempMonth = Integer.parseInt(tempString) - 1;
236
                           tempString = new String(dbuffer, 6, 2);
237
                           int tempDay = Integer.parseInt(tempString);
238
                           Calendar c = Calendar.getInstance();
239
                           c.set(Calendar.YEAR, tempYear);
240
                           c.set(Calendar.MONTH, tempMonth);
241
                           c.set(Calendar.DAY_OF_MONTH, tempDay);
242
                           tempObject = c.getTime();
243
                       } catch (NumberFormatException e) {
244
                       }
245
                       break;
246
                   case 'M': // memo field.
247
                       byte[] mbuffer = new byte[10];
248
                                           buffer.get(mbuffer);
249
                       break;
250
                   case 'N': // number
251
                   case 'F': // floating point number
252
                       byte[] fbuffer = new byte[tempFieldLength];
253
                                           buffer.get(fbuffer);
254
                       try {
255
                           tempString = new String(fbuffer);
256
                           tempObject = Double.valueOf(tempString.trim());
257
                       } catch (NumberFormatException e) {
258
                       }
259
                       break;
260
                   default:
261
                       byte[] defbuffer = new byte[tempFieldLength];
262
                                           buffer.get(defbuffer);
263
                       System.out.println("Do not know how to parse Field type " +
264
                           tempFieldType);
265
                   }
266
                   tempRow[j] = tempObject;
267
                   //                                System.out.println(" Data="+tempObject);
268
               }
269
               // ensure that the full record has been read.
270
               if (tempRecordLength < myHeader.getRecordLength()) {
271
                   byte[] tempbuff = new byte[myHeader.getRecordLength() -
272
                       tempRecordLength];
273
                   buffer.get(tempbuff);
274
                   /* if (tempTelling){
275
                           System.out.println("DBF File has "+(myHeader.getRecordLength()-tempRecordLength)+" extra bytes per record");
276
                           tempTelling = false;
277
                   } */
278
        /*           }
279
           return tempRow;
280
           }
281
         */
282

    
283
        /**
284
         * Retrieve the name of the given column.
285
         *
286
         * @param inIndex ?ndice.
287
         *
288
         * @return nombre del campo.
289
         */
290
        public String getFieldName(int inIndex) {
291
                return myHeader.getFieldName(inIndex).trim();
292
        }
293

    
294
        /**
295
         * Retrieve the type of the given column.
296
         *
297
         * @param inIndex ?ndice.
298
         *
299
         * @return tipo de campo.
300
         */
301
        public char getFieldType(int inIndex) {
302
                return myHeader.getFieldType(inIndex);
303
        }
304

    
305
        /**
306
         * Retrieve the length of the given column.
307
         *
308
         * @param inIndex indice.
309
         *
310
         * @return longitud del field.
311
         */
312
        public int getFieldLength(int inIndex) {
313
                return myHeader.getFieldLength(inIndex);
314
        }
315

    
316
        /*
317
         * Retrieve the value of the given column as string.
318
         *
319
         * @param idField DOCUMENT ME!
320
         * @param idRecord DOCUMENT ME!
321
         *
322
         * @return DOCUMENT ME!
323
         *
324
                 public Object getFieldValue(int idField, long idRecord) throws IOException {
325
                     Object[] tmpReg = getRecord(idRecord);
326
                     return tmpReg[idField];
327
                 }
328
         */
329
        /*
330
         * DOCUMENT ME!
331
         *
332
         * @param idField DOCUMENT ME!
333
         * @param idRecord DOCUMENT ME!
334
         *
335
         * @return DOCUMENT ME!
336
         *
337
                 public double getFieldValueAsDouble(int idField, int idRecord) throws IOException {
338
                     Object[] tmpReg = getRecord(idRecord);
339
                     return (double) Double.parseDouble(tmpReg[idField].toString());
340
                 }
341
         */
342

    
343
        /**
344
         * Retrieve the location of the decimal point.
345
         *
346
         * @param inIndex ?ndice.
347
         *
348
         * @return localizaci?n.
349
         */
350
        public int getFieldDecimalLength(int inIndex) {
351
                return myHeader.getFieldDecimalCount(inIndex);
352
        }
353

    
354
        /**
355
         * read the DBF file into memory.
356
         *
357
         * @param file Fichero.
358
         *
359
         * @throws IOException
360
         */
361
        public void open(File file) throws IOException {
362
                fin = new FileInputStream(file);
363
                channel = fin.getChannel();
364

    
365
        // buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());
366
        buffer = new BigByteBuffer2(channel, FileChannel.MapMode.READ_ONLY);
367

    
368
                // create the header to contain the header information.
369
                myHeader = new DbaseFileHeaderNIO();
370
                myHeader.readHeader(buffer);
371
                
372
                charBuffer = CharBuffer.allocate(myHeader.getRecordLength() - 1);
373
                chars = Charset.forName("ISO-8859-1");
374
                decoder = chars.newDecoder();
375

    
376
        }
377

    
378
        /**
379
         * Removes all data from the dataset
380
         *
381
         * @throws IOException .
382
         */
383
        public void close() throws IOException {
384
                fin.close();
385
                channel.close();
386
        }
387

    
388
        /**
389
         * @return Returns the DbaseFileHeaderNIO.
390
         */
391
        public DbaseFileHeaderNIO getDBaseHeader() {
392
                return myHeader;
393
        }
394
}