Statistics
| Revision:

svn-gvsig-desktop / trunk / libraries / libFMap / src / com / iver / cit / gvsig / fmap / drivers / shp / DbaseFileNIO.java @ 28841

History | View | Annotate | Download (12.7 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
import java.nio.charset.UnsupportedCharsetException;
52

    
53
import javax.swing.JOptionPane;
54

    
55
import org.apache.log4j.Logger;
56

    
57
import com.iver.cit.gvsig.fmap.drivers.dbf.DbfEncodings;
58
import com.iver.utiles.bigfile.BigByteBuffer2;
59

    
60

    
61
/**
62
 * Class to read and write data to a dbase III format file. Creation date:
63
 * (5/15/2001 5:15:13 PM)
64
 */
65
public class DbaseFileNIO {
66
        private static Charset defaultCharset = Charset.defaultCharset();
67

    
68
        // Header information for the DBase File
69
        private DbaseFileHeaderNIO myHeader;
70
        private FileInputStream fin;
71
        private FileChannel channel;
72
        private BigByteBuffer2 buffer;
73

    
74
        CharBuffer charBuffer;
75

    
76
        private Charset charSet;
77

    
78
        /**
79
         * Retrieve number of records in the DbaseFile
80
         *
81
         * @return N?mero de registros.
82
         */
83
        public int getRecordCount() {
84
                return myHeader.getNumRecords();
85
        }
86

    
87
        /**
88
         * Devuelve el n?mero de fields.
89
         *
90
         * @return N?mero de fields.
91
         */
92
        public int getFieldCount() {
93
                return myHeader.getNumFields();
94
        }
95

    
96
        /**
97
         * Devuelve el valor de un boolean a partir de su n?mero de fila y de
98
         * field.
99
         *
100
         * @param rowIndex N?mero de fila.
101
         * @param fieldId N?mero columna.
102
         *
103
         * @return boolean.
104
         */
105
        public boolean getBooleanFieldValue(int rowIndex, int fieldId) {
106
                int recordOffset = (myHeader.getRecordLength() * rowIndex) +
107
                        myHeader.getHeaderLength() + 1;
108

    
109
                //Se calcula el offset del campo
110
                int fieldOffset = 0;
111

    
112
                for (int i = 0; i < (fieldId - 1); i++) {
113
                        fieldOffset += myHeader.getFieldLength(i);
114
                }
115

    
116
                buffer.position(recordOffset + fieldOffset);
117

    
118
                char bool = (char) buffer.get();
119

    
120
                return ((bool == 't') || (bool == 'T') || (bool == 'Y') ||
121
                (bool == 'y'));
122
        }
123

    
124
        /**
125
         * Devuelve el String a partir del n?mero de fila y columna.
126
         *
127
         * @param rowIndex N?mero de fila.
128
         * @param fieldId N?mero de columna.
129
         *
130
         * @return String.
131
         * @throws UnsupportedEncodingException
132
         */
133
        public String getStringFieldValue(int rowIndex, int fieldId) throws UnsupportedEncodingException {
134
                int recordOffset = (myHeader.getRecordLength() * rowIndex) +
135
                        myHeader.getHeaderLength() + 1;
136

    
137
                //Se calcula el offset del campo
138
                int fieldOffset = 0;
139

    
140
                for (int i = 0; i < fieldId; i++) {
141
                        fieldOffset += myHeader.getFieldLength(i);
142
                }
143

    
144
                buffer.position(recordOffset + fieldOffset);
145

    
146
                byte[] data = new byte[myHeader.getFieldLength(fieldId)];
147

    
148
//                ByteBuffer byteBuffer = ByteBuffer.wrap(data);
149

    
150

    
151
                buffer.get(data);
152
                return new String(data, charSet.name());
153
        }
154

    
155
        /**
156
         * Devuelve el Number a partir de una fila y columna.
157
         *
158
         * @param rowIndex N?mero fila.
159
         * @param fieldId N?mero columna.
160
         *
161
         * @return Number.
162
         */
163
        public Number getNumberFieldValue(int rowIndex, int fieldId) {
164
                //System.out.println("rowIndex = "+rowIndex+ " , "+"fieldId = "+fieldId);
165
                int recordOffset = (myHeader.getRecordLength() * rowIndex) +
166
                        myHeader.getHeaderLength() + 1;
167

    
168
                //Se calcula el offset del campo
169
                int fieldOffset = 0;
170

    
171
                for (int i = 0; i < fieldId; i++) {
172
                        fieldOffset += myHeader.getFieldLength(i);
173
                }
174

    
175
                buffer.position(recordOffset + fieldOffset);
176

    
177
                byte[] data = new byte[myHeader.getFieldLength(fieldId)];
178
                buffer.get(data);
179

    
180
                String s = new String(data);
181
                s = s.trim();
182

    
183
                if (getFieldType(fieldId) == 'N') {
184
                        Object tempObject = Double.valueOf(s);
185

    
186
                        return new Double(tempObject.toString());
187
                } else {
188
                        Object tempObject = Integer.valueOf(s);
189

    
190
                        return new Integer(tempObject.toString());
191
                }
192

    
193
                //return 0;
194
        }
195

    
196
        // Retrieve the record at the given index
197

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

    
290
        /**
291
         * Retrieve the name of the given column.
292
         *
293
         * @param inIndex ?ndice.
294
         *
295
         * @return nombre del campo.
296
         */
297
        public String getFieldName(int inIndex) {
298
                byte[] bytes = myHeader.getFieldName(inIndex).trim().getBytes();
299
                String result;
300
                try {
301
                        result = new String(bytes, charSet.name());
302
                        return result;
303
                } catch (UnsupportedEncodingException e) {
304
                        e.printStackTrace();
305
                }
306
                return myHeader.getFieldName(inIndex).trim();
307
        }
308

    
309
        /**
310
         * Retrieve the type of the given column.
311
         *
312
         * @param inIndex ?ndice.
313
         *
314
         * @return tipo de campo.
315
         */
316
        public char getFieldType(int inIndex) {
317
                return myHeader.getFieldType(inIndex);
318
        }
319

    
320
        /**
321
         * Retrieve the length of the given column.
322
         *
323
         * @param inIndex indice.
324
         *
325
         * @return longitud del field.
326
         */
327
        public int getFieldLength(int inIndex) {
328
                return myHeader.getFieldLength(inIndex);
329
        }
330

    
331
        /*
332
         * Retrieve the value of the given column as string.
333
         *
334
         * @param idField DOCUMENT ME!
335
         * @param idRecord DOCUMENT ME!
336
         *
337
         * @return DOCUMENT ME!
338
         *
339
                 public Object getFieldValue(int idField, long idRecord) throws IOException {
340
                     Object[] tmpReg = getRecord(idRecord);
341
                     return tmpReg[idField];
342
                 }
343
         */
344
        /*
345
         * DOCUMENT ME!
346
         *
347
         * @param idField DOCUMENT ME!
348
         * @param idRecord DOCUMENT ME!
349
         *
350
         * @return DOCUMENT ME!
351
         *
352
                 public double getFieldValueAsDouble(int idField, int idRecord) throws IOException {
353
                     Object[] tmpReg = getRecord(idRecord);
354
                     return (double) Double.parseDouble(tmpReg[idField].toString());
355
                 }
356
         */
357

    
358
        /**
359
         * Retrieve the location of the decimal point.
360
         *
361
         * @param inIndex ?ndice.
362
         *
363
         * @return localizaci?n.
364
         */
365
        public int getFieldDecimalLength(int inIndex) {
366
                return myHeader.getFieldDecimalCount(inIndex);
367
        }
368

    
369
        /**
370
         * read the DBF file into memory.
371
         *
372
         * @param file Fichero.
373
         *
374
         * @throws IOException
375
         */
376
        public void open(File file) throws IOException {
377
                fin = new FileInputStream(file);
378
                channel = fin.getChannel();
379

    
380
        // buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());
381
        buffer = new BigByteBuffer2(channel, FileChannel.MapMode.READ_ONLY);
382

    
383
                // create the header to contain the header information.
384
                myHeader = new DbaseFileHeaderNIO();
385
                myHeader.readHeader(buffer);
386

    
387
                charBuffer = CharBuffer.allocate(myHeader.getRecordLength() - 1);
388
                String charSetName = DbfEncodings.getInstance().getCharsetForDbfId(myHeader.getLanguageID());
389
                if (charSetName == null)
390
                {
391
                        charSet = Charset.defaultCharset();
392
                        System.out.println("Opening file " + file.getName() + " with languageId = " + myHeader.getLanguageID());
393
                }
394
                else
395
                {
396
                        System.out.println("Opening file " + file.getName() + " with encoding " + charSetName);
397
                        if (charSetName.equalsIgnoreCase("UNKNOWN"))
398
                                charSet = Charset.defaultCharset();
399
                        else{
400
                                try{
401
                                        charSet = Charset.forName(charSetName);
402
                                }catch (UnsupportedCharsetException e) {
403
                                        JOptionPane.showConfirmDialog(null, "Unsupported CharSet for the System");
404
                                        Logger.getLogger(this.getClass()).error(e.getLocalizedMessage(), e);
405
                                        charSet = Charset.defaultCharset();
406
                                }
407
                        }
408
                }
409

    
410
        }
411

    
412
        /**
413
         * Removes all data from the dataset
414
         *
415
         * @throws IOException .
416
         */
417
        public void close() throws IOException {
418
                fin.close();
419
                channel.close();
420
        }
421
        public static Charset getDefaultCharset() {
422
                return defaultCharset;
423
        }
424

    
425
        public static void setDefaultCharset(Charset defaultCharset) {
426
                DbaseFileNIO.defaultCharset = defaultCharset;
427
        }
428

    
429
        public void setCharSet(Charset charSet) {
430
                this.charSet = charSet;
431

    
432
        }
433

    
434
        public Charset getCharSet() {
435
                return charSet;
436
        }
437

    
438
        /**
439
         * @return Returns the DbaseFileHeaderNIO.
440
         */
441
        public DbaseFileHeaderNIO getDBaseHeader() {
442
                return myHeader;
443
        }
444
}