Statistics
| Revision:

root / trunk / libraries / libFMap / src / com / iver / cit / gvsig / fmap / drivers / dbf / DbaseFile.java @ 6990

History | View | Annotate | Download (12.3 KB)

1
/*
2
 * Created on 16-feb-2004
3
 *
4
 * To change the template for this generated file go to
5
 * Window>Preferences>Java>Code Generation>Code and Comments
6
 */
7
package com.iver.cit.gvsig.fmap.drivers.dbf;
8

    
9

    
10
/**
11
 */
12
import java.io.File;
13
import java.io.FileNotFoundException;
14
import java.io.IOException;
15
import java.io.RandomAccessFile;
16
import java.io.UnsupportedEncodingException;
17
import java.nio.ByteBuffer;
18
import java.nio.channels.FileChannel;
19
import java.nio.charset.Charset;
20

    
21
import com.iver.utiles.bigfile.BigByteBuffer2;
22

    
23

    
24
/**
25
 * Class to read and write data to a dbase III format file. Creation date:
26
 * (5/15/2001 5:15:13 PM)
27
 */
28
public class DbaseFile {
29
    // Header information for the DBase File
30
    private DbaseFileHeader myHeader;
31
    private RandomAccessFile raf;
32
    private FileChannel channel;
33
    private BigByteBuffer2 buffer;
34
    private FileChannel.MapMode mode;
35
    
36
    private int posActual = -1;
37
        private int recordOffset;
38
        private ByteBuffer cachedRecord = null;
39
        private byte[] bytesCachedRecord = null;
40
        
41
          private Charset chars;
42

    
43

    
44
    // Retrieve number of records in the DbaseFile
45
    public int getRecordCount() {
46
        return myHeader.getNumRecords();
47
    }
48

    
49
    /**
50
     * DOCUMENT ME!
51
     *
52
     * @return DOCUMENT ME!
53
     */
54
    public int getFieldCount() {
55
        return myHeader.getNumFields();
56
    }
57

    
58
    /**
59
     * DOCUMENT ME!
60
     *
61
     * @param rowIndex DOCUMENT ME!
62
     * @param fieldId DOCUMENT ME!
63
     *
64
     * @return DOCUMENT ME!
65
     */
66
    public boolean getBooleanFieldValue(int rowIndex, int fieldId) {
67
        int recordOffset = (myHeader.getRecordLength() * rowIndex) +
68
            myHeader.getHeaderLength() + 1;
69

    
70
        //Se calcula el offset del campo
71
        int fieldOffset = 0;
72

    
73
        for (int i = 0; i < (fieldId - 1); i++) {
74
            fieldOffset += myHeader.getFieldLength(i);
75
        }
76

    
77
        buffer.position(recordOffset + fieldOffset);
78

    
79
        char bool = (char) buffer.get();
80

    
81
        return ((bool == 't') || (bool == 'T') || (bool == 'Y') ||
82
        (bool == 'y'));
83
    }
84

    
85
    /**
86
     * DOCUMENT ME!
87
     *
88
     * @param rowIndex DOCUMENT ME!
89
     * @param fieldId DOCUMENT ME!
90
     *
91
     * @return DOCUMENT ME!
92
     * @throws UnsupportedEncodingException 
93
     */
94
    public String getStringFieldValue(int rowIndex, int fieldId) throws UnsupportedEncodingException {
95
            int fieldOffset = myHeader.getFieldDescription(fieldId).myFieldDataAddress;
96
            byte[] data = new byte[myHeader.getFieldLength(fieldId)];
97
            if (rowIndex != posActual)
98
            {
99
                    recordOffset = (myHeader.getRecordLength() * rowIndex) +
100
                    myHeader.getHeaderLength() + 1;
101
                
102
        
103
                /* System.err.println("getStringFieldValue: rowIndex = " + rowIndex);
104
                System.err.println("recordOffset = " + recordOffset + " fieldOffset=" + fieldOffset); */
105
                buffer.position(recordOffset);
106
                buffer.get(bytesCachedRecord);
107
                cachedRecord = ByteBuffer.wrap(bytesCachedRecord);
108
                posActual = rowIndex;
109
                
110
            }
111
                cachedRecord.position(fieldOffset);
112
                cachedRecord.get(data);
113

    
114

    
115
        return new String(data, chars.name());
116
            
117
    }
118

    
119
    // Retrieve the record at the given index
120

    
121
    /*    public Object[] getRecord(long inIndex) throws IOException {
122
       long nRecordOffset = (myHeader.getRecordLength() * inIndex) +
123
           myHeader.getHeaderLength();
124
       // retrieve the record length
125
       int tempNumFields = myHeader.getNumFields();
126
       // storage for the actual values
127
       Object[] tempRow = new Object[tempNumFields];
128
           buffer.position((int) nRecordOffset);
129
           // read the deleted flag
130
           char tempDeleted = (char) buffer.get();
131
           // read the record length
132
           int tempRecordLength = 1; // for the deleted character just read.
133
           // read the Fields
134
           for (int j = 0; j < tempNumFields; j++) {
135
               // find the length of the field.
136
               int tempFieldLength = myHeader.getFieldLength(j);
137
               tempRecordLength = tempRecordLength + tempFieldLength;
138
               // find the field type
139
               char tempFieldType = myHeader.getFieldType(j);
140
               //System.out.print("Reading Name="+myHeader.getFieldName(j)+" Type="+tempFieldType +" Length="+tempFieldLength);
141
               // read the data.
142
               Object tempObject = null;
143
               switch (tempFieldType) {
144
               case 'L': // logical data type, one character (T,t,F,f,Y,y,N,n)
145
                   char tempChar = (char) buffer.get();
146
                   if ((tempChar == 'T') || (tempChar == 't') ||
147
                           (tempChar == 'Y') || (tempChar == 'y')) {
148
                       tempObject = new Boolean(true);
149
                   } else {
150
                       tempObject = new Boolean(false);
151
                   }
152
                   break;
153
               case 'C': // character record.
154
                   byte[] sbuffer = new byte[tempFieldLength];
155
                                       buffer.get(sbuffer);
156
                   tempObject = new String(sbuffer, "ISO-8859-1").trim();
157
                   break;
158
               case 'D': // date data type.
159
                   byte[] dbuffer = new byte[8];
160
                                       buffer.get(dbuffer);
161
                   String tempString = new String(dbuffer, 0, 4);
162
                   try {
163
                       int tempYear = Integer.parseInt(tempString);
164
                       tempString = new String(dbuffer, 4, 2);
165
                       int tempMonth = Integer.parseInt(tempString) - 1;
166
                       tempString = new String(dbuffer, 6, 2);
167
                       int tempDay = Integer.parseInt(tempString);
168
                       Calendar c = Calendar.getInstance();
169
                       c.set(Calendar.YEAR, tempYear);
170
                       c.set(Calendar.MONTH, tempMonth);
171
                       c.set(Calendar.DAY_OF_MONTH, tempDay);
172
                       tempObject = c.getTime();
173
                   } catch (NumberFormatException e) {
174
                   }
175
                   break;
176
               case 'M': // memo field.
177
                   byte[] mbuffer = new byte[10];
178
                                       buffer.get(mbuffer);
179
                   break;
180
               case 'N': // number
181
               case 'F': // floating point number
182
                   byte[] fbuffer = new byte[tempFieldLength];
183
                                       buffer.get(fbuffer);
184
                   try {
185
                       tempString = new String(fbuffer);
186
                       tempObject = Double.valueOf(tempString.trim());
187
                   } catch (NumberFormatException e) {
188
                   }
189
                   break;
190
               default:
191
                   byte[] defbuffer = new byte[tempFieldLength];
192
                                       buffer.get(defbuffer);
193
                   System.out.println("Do not know how to parse Field type " +
194
                       tempFieldType);
195
               }
196
               tempRow[j] = tempObject;
197
               //                                System.out.println(" Data="+tempObject);
198
           }
199
           // ensure that the full record has been read.
200
           if (tempRecordLength < myHeader.getRecordLength()) {
201
               byte[] tempbuff = new byte[myHeader.getRecordLength() -
202
                   tempRecordLength];
203
               buffer.get(tempbuff);
204
               /* if (tempTelling){
205
                       System.out.println("DBF File has "+(myHeader.getRecordLength()-tempRecordLength)+" extra bytes per record");
206
                       tempTelling = false;
207
               } */
208
    /*           }
209
       return tempRow;
210
       }
211
     */
212

    
213
    /**
214
     * Retrieve the name of the given column.
215
     *
216
     * @param inIndex DOCUMENT ME!
217
     *
218
     * @return DOCUMENT ME!
219
     */
220
    public String getFieldName(int inIndex) {
221
        return myHeader.getFieldName(inIndex).trim();
222
    }
223

    
224
    /**
225
     * Retrieve the type of the given column.
226
     *
227
     * @param inIndex DOCUMENT ME!
228
     *
229
     * @return DOCUMENT ME!
230
     */
231
    public char getFieldType(int inIndex) {
232
        return myHeader.getFieldType(inIndex);
233
    }
234

    
235
    /**
236
     * Retrieve the length of the given column.
237
     *
238
     * @param inIndex DOCUMENT ME!
239
     *
240
     * @return DOCUMENT ME!
241
     */
242
    public int getFieldLength(int inIndex) {
243
        return myHeader.getFieldLength(inIndex);
244
    }
245

    
246
    /*
247
     * Retrieve the value of the given column as string.
248
     *
249
     * @param idField DOCUMENT ME!
250
     * @param idRecord DOCUMENT ME!
251
     *
252
     * @return DOCUMENT ME!
253
     *
254
             public Object getFieldValue(int idField, long idRecord) throws IOException {
255
                 Object[] tmpReg = getRecord(idRecord);
256
                 return tmpReg[idField];
257
             }
258
     */
259
    /*
260
     * DOCUMENT ME!
261
     *
262
     * @param idField DOCUMENT ME!
263
     * @param idRecord DOCUMENT ME!
264
     *
265
     * @return DOCUMENT ME!
266
     *
267
             public double getFieldValueAsDouble(int idField, int idRecord) throws IOException {
268
                 Object[] tmpReg = getRecord(idRecord);
269
                 return (double) Double.parseDouble(tmpReg[idField].toString());
270
             }
271
     */
272

    
273
    /**
274
     * Retrieve the location of the decimal point.
275
     *
276
     * @param inIndex DOCUMENT ME!
277
     *
278
     * @return DOCUMENT ME!
279
     */
280
    public int getFieldDecimalLength(int inIndex) {
281
        return myHeader.getFieldDecimalCount(inIndex);
282
    }
283

    
284
    /**
285
     * read the DBF file into memory.
286
     *
287
     * @param file DOCUMENT ME!
288
     *
289
     * @throws IOException DOCUMENT ME!
290
     */
291
    public void open(File file) throws IOException {
292
            /* 
293
            01h         DOS USA        code page 437
294
            02h         DOS Multilingual        code page 850
295
            03h         Windows ANSI        code page 1252
296
            04h         Standard Macintosh
297
            64h         EE MS-DOS        code page 852
298
            65h         Nordic MS-DOS        code page 865
299
            66h         Russian MS-DOS        code page 866
300
            67h         Icelandic MS-DOS
301
            68h         Kamenicky (Czech) MS-DOS
302
            69h         Mazovia (Polish) MS-DOS
303
            6Ah         Greek MS-DOS (437G)
304
            6Bh         Turkish MS-DOS
305
            96h         Russian Macintosh
306
            97h         Eastern European Macintosh
307
            98h         Greek Macintosh
308
            C8h         Windows EE        code page 1250
309
            C9h         Russian Windows
310
            CAh         Turkish Windows
311
            CBh                Greek Windows
312
            */
313
        if (file.canWrite()){
314
                try{
315
                        raf = new RandomAccessFile(file, "rw");
316
                        mode = FileChannel.MapMode.READ_WRITE;
317
                }catch (FileNotFoundException e) {
318
                        raf = new RandomAccessFile(file, "r");
319
                mode = FileChannel.MapMode.READ_ONLY;
320
                        }
321
        } else {
322
            raf = new RandomAccessFile(file, "r");
323
            mode = FileChannel.MapMode.READ_ONLY;
324
        }
325
        channel = raf.getChannel();
326

    
327
        // buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());
328
        buffer = new BigByteBuffer2(channel, mode);
329

    
330
        // create the header to contain the header information.
331
        myHeader = new DbaseFileHeader();
332
        myHeader.readHeader(buffer);
333
        switch (myHeader.getLanguageID())
334
        {
335
        case 0x01:
336
                chars = Charset.forName("US-ASCII");
337
                break;
338
        case 0x02:
339
                chars = Charset.forName("ISO-8859-1");
340
                break;
341
        case 0x03:
342
                chars = Charset.forName("windows-1252");
343
                break;
344
        case 0x04:
345
                chars = Charset.forName("mac");
346
                break;
347
        case 0x64:
348
                chars = Charset.forName("ISO-8859-1");
349
                break;
350
        case 0x65:
351
                chars = Charset.forName("ISO-8859-1");
352
                break;
353
        case 0x66:
354
                chars = Charset.forName("ISO-8859-1");
355
                break;
356
        case 0x67:
357
                chars = Charset.forName("ISO-8859-1");
358
                break;
359
        case 0x68:
360
                chars = Charset.forName("greek");
361
                break;
362
        case 0x69:
363
                chars = Charset.forName("ISO-8859-1");
364
                break;
365
        case 0x6A:
366
                chars = Charset.forName("greek");
367
                break;
368
        case 0x6B:
369
                chars = Charset.forName("ISO-8859-1");
370
                break;
371
                
372
        default:
373
                chars = Charset.forName("ISO-8859-1");
374
        }
375
        bytesCachedRecord = new byte[myHeader.getRecordLength()];
376
    }
377

    
378
    /**
379
     * Removes all data from the dataset
380
     *
381
     * @throws IOException DOCUMENT ME!
382
     */
383
    public void close() throws IOException {
384
        raf.close();
385
        channel.close();
386
        buffer = null;
387
    }
388

    
389
    public FileChannel getWriteChannel() {
390
        return channel;
391
    }
392
}