Statistics
| Revision:

root / branches / v2_0_0_prep / libraries / libFMap_dalfile / src / org / gvsig / fmap / dal / store / dbf / utils / DbaseFileHeader.java @ 33331

History | View | Annotate | Download (23.7 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 org.gvsig.fmap.dal.store.dbf.utils;
8

    
9
import java.io.IOException;
10
import java.io.UnsupportedEncodingException;
11
import java.nio.ByteBuffer;
12
import java.nio.ByteOrder;
13
import java.nio.channels.FileChannel;
14
import java.util.Calendar;
15
import java.util.Date;
16
import java.util.Iterator;
17

    
18
import org.gvsig.fmap.dal.DataTypes;
19
import org.gvsig.fmap.dal.exception.UnsupportedVersionException;
20
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
21
import org.gvsig.fmap.dal.feature.FeatureType;
22
import org.gvsig.fmap.dal.feature.exception.AttributeFeatureTypeNotSuportedException;
23
import org.gvsig.tools.ToolsLocator;
24
import org.gvsig.utils.bigfile.BigByteBuffer2;
25

    
26

    
27

    
28
/**
29
 * Class to represent the header of a Dbase III file. Creation date: (5/15/2001
30
 * 5:15:30 PM)
31
 */
32
public class DbaseFileHeader {
33
    // Constant for the size of a record
34
    private int FILE_DESCRIPTOR_SIZE = 32;
35

    
36
        // type of the file, must be 03h
37
        private static final byte MAGIC = 0x03;
38

    
39
        private static final int MINIMUM_HEADER = 33;
40

    
41
    // type of the file, must be 03h
42
    private int myFileType = 0x03;
43

    
44
    // Date the file was last updated.
45
    private Date myUpdateDate = new Date();
46

    
47
    // Number of records in the datafile
48
        private int myNumRecords = 0;
49

    
50
    // Length of the header structure
51
    private int myHeaderLength;
52

    
53
    // Length of the records
54
    private int myRecordLength;
55

    
56
    // Number of fields in the record.
57
    private int myNumFields;
58

    
59
    // collection of header records.
60
    private DbaseFieldDescriptor[] myFieldDescriptions;
61

    
62
        private byte myLanguageID;
63

    
64
    /**
65
     * DbaseFileHreader constructor comment.
66
     */
67
    public DbaseFileHeader() {
68
        super();
69
    }
70

    
71
    /**
72
     * Add a column to this DbaseFileHeader. The type is one of (C N L or D)
73
     * character, number, logical(true/false), or date. The Field length is
74
     * the total length in bytes reserved for this column. The decimal count
75
     * only applies to numbers(N), and floating point values (F), and refers
76
     * to the number of characters to reserve after the decimal point.
77
     *
78
     * @param inFieldName DOCUMENT ME!
79
     * @param inFieldType DOCUMENT ME!
80
     * @param inFieldLength DOCUMENT ME!
81
     * @param inDecimalCount DOCUMENT ME!
82
     * @throws BadFieldDriverException
83
     *
84
     * @throws Exception DOCUMENT ME!
85
     */
86
    public void addColumn(String inFieldName, char inFieldType,
87
        int inFieldLength, int inDecimalCount)
88
                        throws AttributeFeatureTypeNotSuportedException {
89
        if (inFieldLength <= 0) {
90
            inFieldLength = 1;
91
        }
92

    
93
        if (myFieldDescriptions == null) {
94
            myFieldDescriptions = new DbaseFieldDescriptor[0];
95
        }
96

    
97
        int tempLength = 1; // the length is used for the offset, and there is a * for deleted as the first byte
98
        DbaseFieldDescriptor[] tempFieldDescriptors = new DbaseFieldDescriptor[myFieldDescriptions.length +
99
            1];
100

    
101
        for (int i = 0; i < myFieldDescriptions.length; i++) {
102
            myFieldDescriptions[i].myFieldDataAddress = tempLength;
103
            tempLength = tempLength + myFieldDescriptions[i].myFieldLength;
104
            tempFieldDescriptors[i] = myFieldDescriptions[i];
105
        }
106

    
107
        tempFieldDescriptors[myFieldDescriptions.length] = new DbaseFieldDescriptor();
108
        tempFieldDescriptors[myFieldDescriptions.length].myFieldLength = inFieldLength;
109
        tempFieldDescriptors[myFieldDescriptions.length].myDecimalCount = inDecimalCount;
110
        tempFieldDescriptors[myFieldDescriptions.length].myFieldDataAddress = tempLength;
111

    
112
        // set the field name
113
        String tempFieldName = inFieldName;
114

    
115
        if (tempFieldName == null) {
116
            tempFieldName = "NoName";
117
        }
118

    
119
        if (tempFieldName.length() > 11) {
120
            tempFieldName = tempFieldName.substring(0, 11);
121
            warn("FieldName " + inFieldName +
122
                " is longer than 11 characters, truncating to " +
123
                tempFieldName);
124
        }
125

    
126
        tempFieldDescriptors[myFieldDescriptions.length].myFieldName = tempFieldName;
127
        tempFieldDescriptors[myFieldDescriptions.length].myFieldName_trim = tempFieldName
128
                                .trim();
129

    
130
        // the field type
131
        if ((inFieldType == 'C') || (inFieldType == 'c')) {
132
            tempFieldDescriptors[myFieldDescriptions.length].myFieldType = 'C';
133

    
134
            if (inFieldLength > 254) {
135
                warn("Field Length for " + inFieldName + " set to " +
136
                    inFieldLength +
137
                    " Which is longer than 254, not consistent with dbase III");
138
            }
139
        } else if ((inFieldType == 'S') || (inFieldType == 's')) {
140
            tempFieldDescriptors[myFieldDescriptions.length].myFieldType = 'C';
141
            warn("Field type for " + inFieldName +
142
                " set to S which is flat out wrong people!, I am setting this to C, in the hopes you meant character.");
143

    
144
            if (inFieldLength > 254) {
145
                warn("Field Length for " + inFieldName + " set to " +
146
                    inFieldLength +
147
                    " Which is longer than 254, not consistent with dbase III");
148
            }
149

    
150
            tempFieldDescriptors[myFieldDescriptions.length].myFieldLength = 8;
151
        } else if ((inFieldType == 'D') || (inFieldType == 'd')) {
152
            tempFieldDescriptors[myFieldDescriptions.length].myFieldType = 'D';
153

    
154
            if (inFieldLength != 8) {
155
                warn("Field Length for " + inFieldName + " set to " +
156
                    inFieldLength + " Setting to 8 digets YYYYMMDD");
157
            }
158

    
159
            tempFieldDescriptors[myFieldDescriptions.length].myFieldLength = 8;
160
        } else if ((inFieldType == 'F') || (inFieldType == 'f')) {
161
            tempFieldDescriptors[myFieldDescriptions.length].myFieldType = 'F';
162

    
163
            if (inFieldLength > 20) {
164
                warn("Field Length for " + inFieldName + " set to " +
165
                    inFieldLength +
166
                    " Preserving length, but should be set to Max of 20 not valid for dbase IV, and UP specification, not present in dbaseIII.");
167
            }
168
        } else if ((inFieldType == 'N') || (inFieldType == 'n')) {
169
            tempFieldDescriptors[myFieldDescriptions.length].myFieldType = 'N';
170

    
171
            if (inFieldLength > 18) {
172
                warn("Field Length for " + inFieldName + " set to " +
173
                    inFieldLength +
174
                    " Preserving length, but should be set to Max of 18 for dbase III specification.");
175
            }
176

    
177
            if (inDecimalCount < 0) {
178
                warn("Field Decimal Position for " + inFieldName + " set to " +
179
                    inDecimalCount +
180
                    " Setting to 0 no decimal data will be saved.");
181
                tempFieldDescriptors[myFieldDescriptions.length].myDecimalCount = 0;
182
            }
183
//
184
//            if (inDecimalCount > (inFieldLength - 1)) {
185
//                warn("Field Decimal Position for " + inFieldName + " set to " +
186
//                    inDecimalCount + " Setting to " + (inFieldLength - 1) +
187
//                    " no non decimal data will be saved.");
188
//                tempFieldDescriptors[myFieldDescriptions.length].myDecimalCount = inFieldLength -
189
//                    1;
190
//            }
191
        } else if ((inFieldType == 'L') || (inFieldType == 'l')) {
192
            tempFieldDescriptors[myFieldDescriptions.length].myFieldType = 'L';
193

    
194
            if (inFieldLength != 1) {
195
                warn("Field Length for " + inFieldName + " set to " +
196
                    inFieldLength +
197
                    " Setting to length of 1 for logical fields.");
198
            }
199

    
200
            tempFieldDescriptors[myFieldDescriptions.length].myFieldLength = 1;
201
        } else {
202
            throw new AttributeFeatureTypeNotSuportedException(tempFieldName,
203
                                        inFieldType, ToolsLocator.getDataTypesManager().getTypeName(inFieldType), "DBF");
204
        }
205

    
206
        // the length of a record
207
        tempLength = tempLength +
208
            tempFieldDescriptors[myFieldDescriptions.length].myFieldLength;
209

    
210
        // set the new fields.
211
        myFieldDescriptions = tempFieldDescriptors;
212
        myHeaderLength = 33 + (32 * myFieldDescriptions.length);
213
        myNumFields = myFieldDescriptions.length;
214
        myRecordLength = tempLength;
215
    }
216

    
217
    /**
218
     * Remove a column from this DbaseFileHeader.
219
     *
220
     * @param inFieldName DOCUMENT ME!
221
     *
222
     * @return index of the removed column, -1 if no found
223
     */
224
    public int removeColumn(String inFieldName) {
225
        int retCol = -1;
226
        int tempLength = 1;
227
        DbaseFieldDescriptor[] tempFieldDescriptors = new DbaseFieldDescriptor[myFieldDescriptions.length -
228
            1];
229

    
230
        for (int i = 0, j = 0; i < myFieldDescriptions.length; i++) {
231
            if (!inFieldName.equalsIgnoreCase(
232
                        myFieldDescriptions[i].myFieldName.trim())) {
233
                // if this is the last field and we still haven't found the
234
                // named field
235
                if ((i == j) && (i == (myFieldDescriptions.length - 1))) {
236
                    System.err.println("Could not find a field named '" +
237
                        inFieldName + "' for removal");
238

    
239
                    return retCol;
240
                }
241

    
242
                tempFieldDescriptors[j] = myFieldDescriptions[i];
243
                tempFieldDescriptors[j].myFieldDataAddress = tempLength;
244
                tempLength += tempFieldDescriptors[j].myFieldLength;
245

    
246
                // only increment j on non-matching fields
247
                j++;
248
            } else {
249
                retCol = i;
250
            }
251
        }
252

    
253
        // set the new fields.
254
        myFieldDescriptions = tempFieldDescriptors;
255
        myHeaderLength = 33 + (32 * myFieldDescriptions.length);
256
        myNumFields = myFieldDescriptions.length;
257
        myRecordLength = tempLength;
258

    
259
        return retCol;
260
    }
261

    
262
    /**
263
     * DOCUMENT ME!
264
     *
265
     * @param inWarn DOCUMENT ME!
266
     */
267
    private void warn(String inWarn) {
268
        //TODO Descomentar esto cuando tenga la clase warning support
269
        //            warnings.warn(inWarn);
270
    }
271

    
272
    /**
273
     * Return the Field Descriptor for the given field.
274
     *
275
     * @param inIndex DOCUMENT ME!
276
     *
277
     * @return DOCUMENT ME!
278
     */
279
    public DbaseFieldDescriptor getFieldDescription(int inIndex) {
280
        return myFieldDescriptions[inIndex];
281
    }
282

    
283
    // Retrieve the length of the field at the given index
284
    public int getFieldLength(int inIndex) {
285
        return myFieldDescriptions[inIndex].myFieldLength;
286
    }
287

    
288
    // Retrieve the location of the decimal point within the field.
289
    public int getFieldDecimalCount(int inIndex) {
290
        return myFieldDescriptions[inIndex].myDecimalCount;
291
    }
292

    
293
    // Retrieve the Name of the field at the given index
294
    public String getFieldName(int inIndex) {
295
        return myFieldDescriptions[inIndex].myFieldName;
296
    }
297

    
298
    public int getFieldIndex(String name) {
299
                for (int i = 0; i < myFieldDescriptions.length; i++) {
300
                        if (myFieldDescriptions[i].myFieldName_trim
301
                                        .equalsIgnoreCase(name)) {
302
                                return i;
303
                        }
304
                }
305
                return -1;
306
        }
307

    
308
    // Retrieve the type of field at the given index
309
    public char getFieldType(int inIndex) {
310
        return myFieldDescriptions[inIndex].myFieldType;
311
    }
312

    
313
    /**
314
     * Return the date this file was last updated.
315
     *
316
     * @return DOCUMENT ME!
317
     */
318
    public Date getLastUpdateDate() {
319
        return myUpdateDate;
320
    }
321

    
322
     /**
323
     * Return the number of fields in the records.
324
     *
325
     * @return DOCUMENT ME!
326
     */
327
    public int getNumFields() {
328
        return myNumFields;
329
    }
330

    
331
    /**
332
     * Return the number of records in the file
333
     *
334
     * @return DOCUMENT ME!
335
     */
336
    public int getNumRecords() {
337
        return myNumRecords;
338
    }
339

    
340
    /**
341
     * Return the length of the records in bytes.
342
     *
343
     * @return DOCUMENT ME!
344
     */
345
    public int getRecordLength() {
346
        return myRecordLength;
347
    }
348

    
349
    /**
350
     * Return the length of the header
351
     *
352
     * @return DOCUMENT ME!
353
     */
354
    public int getHeaderLength() {
355
        return myHeaderLength;
356
    }
357

    
358
        /**
359
         * Read the header data from the DBF file.
360
         *
361
         * @param in
362
         *            DOCUMENT ME!
363
         * @throws UnsupportedVersionException
364
         * @throws UnsupportedEncodingException
365
         *
366
         * @throws IOException
367
         *             DOCUMENT ME!
368
         */
369
    public void readHeader(BigByteBuffer2 in, String charsName)
370
                        throws UnsupportedVersionException, UnsupportedEncodingException {
371
        // type of file.
372
        myFileType = in.get();
373

    
374
        if (myFileType != 0x03) {
375
            throw new UnsupportedVersionException("DBF", Integer
376
                                        .toHexString(myFileType));
377
        }
378

    
379
        // parse the update date information.
380
        int tempUpdateYear = in.get();
381
        int tempUpdateMonth = in.get();
382
        int tempUpdateDay = in.get();
383
        tempUpdateYear = tempUpdateYear + 1900;
384

    
385
        Calendar c = Calendar.getInstance();
386
        c.set(Calendar.YEAR, tempUpdateYear);
387
        c.set(Calendar.MONTH, tempUpdateMonth - 1);
388
        c.set(Calendar.DATE, tempUpdateDay);
389
        myUpdateDate = c.getTime();
390

    
391
        // read the number of records.
392
        in.order(ByteOrder.LITTLE_ENDIAN);
393
        myNumRecords = in.getInt();
394

    
395
        // read the length of the header structure.
396
        myHeaderLength = in.getShort();
397

    
398
        // read the length of a record
399
        myRecordLength = in.getShort(); //posicon 0h
400

    
401
        in.order(ByteOrder.BIG_ENDIAN);
402

    
403
        // skip the reserved bytes in the header.
404
        // in.position(in.position() + 20);
405

    
406
        // Leemos el byte de language
407
        in.position(29);
408
        myLanguageID = in.get();
409
        if (charsName == null) {
410
                charsName = getCharsetName();
411
                }
412

    
413

    
414
        // Posicionamos para empezar a leer los campos.
415
        in.position(32);
416

    
417
        // calculate the number of Fields in the header
418
        myNumFields = (myHeaderLength - FILE_DESCRIPTOR_SIZE - 1) / FILE_DESCRIPTOR_SIZE;
419

    
420
        // read all of the header records
421
        myFieldDescriptions = new DbaseFieldDescriptor[myNumFields];
422
        int fieldOffset = 0;
423

    
424
        for (int i = 0; i < myNumFields; i++) {
425
            myFieldDescriptions[i] = new DbaseFieldDescriptor();
426

    
427
            // read the field name
428
            byte[] buffer = new byte[11];
429
            in.get(buffer);
430
            if (charsName != null) {
431
                                myFieldDescriptions[i].myFieldName = new String(buffer,
432
                                                charsName);
433
                        } else {
434
                                myFieldDescriptions[i].myFieldName = new String(buffer);
435
                        }
436
            myFieldDescriptions[i].myFieldName_trim = myFieldDescriptions[i].myFieldName
437
                                        .trim();
438

    
439
            // read the field type
440
            myFieldDescriptions[i].myFieldType = (char) in.get();
441

    
442
            // read the field data address, offset from the start of the record.
443
            myFieldDescriptions[i].myFieldDataAddress = in.getInt();
444

    
445
            // read the field length in bytes
446
            int tempLength = in.get();
447

    
448
            if (tempLength < 0) {
449
                tempLength = tempLength + 256;
450
            }
451

    
452
            myFieldDescriptions[i].myFieldLength = tempLength;
453

    
454
            // read the field decimal count in bytes
455
            myFieldDescriptions[i].myDecimalCount = in.get();
456

    
457
            // NUEVO: Calculamos los offsets aqu? para no
458
            // tener que recalcular cada vez que nos piden
459
            // algo.
460
            myFieldDescriptions[i].myFieldDataAddress = fieldOffset;
461
            fieldOffset += tempLength;
462
            // Fin NUEVO
463
            // read the reserved bytes.
464
            in.position(in.position() + 14);
465
        }
466

    
467
        // Last byte is a marker for the end of the field definitions.
468
        in.get();
469
    }
470

    
471
    /**
472
     * Set the number of records in the file
473
     *
474
     * @param inNumRecords DOCUMENT ME!
475
     */
476
    public void setNumRecords(int inNumRecords) {
477
        myNumRecords = inNumRecords;
478
    }
479

    
480
    /*
481
     * Write the header data to the DBF file.
482
     *
483
     * @param out DOCUMENT ME!
484
     *
485
     * @throws Exception DOCUMENT ME!
486
     *
487
           public void writeHeader(LEDataOutputStream out) throws Exception {
488
               // write the output file type.
489
               out.writeByte(myFileType);
490
               // write the date stuff
491
               Calendar c = Calendar.getInstance();
492
               c.setTime(new Date());
493
               out.writeByte(c.get(Calendar.YEAR) - 1900);
494
               out.writeByte(c.get(Calendar.MONTH) + 1);
495
               out.writeByte(c.get(Calendar.DAY_OF_MONTH));
496
               // write the number of records in the datafile.
497
               out.writeInt(myNumRecords);
498
               // write the length of the header structure.
499
               out.writeShort(myHeaderLength);
500
               // write the length of a record
501
               out.writeShort(myRecordLength);
502
               // write the reserved bytes in the header
503
               for (int i = 0; i < 20; i++)
504
                   out.writeByte(0);
505
               // write all of the header records
506
               int tempOffset = 0;
507
               for (int i = 0; i < myFieldDescriptions.length; i++) {
508
                   // write the field name
509
                   for (int j = 0; j < 11; j++) {
510
                       if (myFieldDescriptions[i].myFieldName.length() > j) {
511
                           out.writeByte((int) myFieldDescriptions[i].myFieldName.charAt(
512
                                   j));
513
                       } else {
514
                           out.writeByte(0);
515
                       }
516
                   }
517
                   // write the field type
518
                   out.writeByte(myFieldDescriptions[i].myFieldType);
519
                   // write the field data address, offset from the start of the record.
520
                   out.writeInt(tempOffset);
521
                   tempOffset += myFieldDescriptions[i].myFieldLength;
522
                   // write the length of the field.
523
                   out.writeByte(myFieldDescriptions[i].myFieldLength);
524
                   // write the decimal count.
525
                   out.writeByte(myFieldDescriptions[i].myDecimalCount);
526
                   // write the reserved bytes.
527
                   for (int j = 0; j < 14; j++)
528
                       out.writeByte(0);
529
               }
530
               // write the end of the field definitions marker
531
               out.writeByte(0x0D);
532
           }
533
     */
534

    
535
    /**
536
     * Class for holding the information assicated with a record.
537
     */
538
    class DbaseFieldDescriptor {
539
        // Field Name
540
        String myFieldName;
541

    
542
        String myFieldName_trim;
543

    
544
        // Field Type (C N L D F or M)
545
        char myFieldType;
546

    
547
        // Field Data Address offset from the start of the record.
548
        int myFieldDataAddress;
549

    
550
        // Length of the data in bytes
551
        int myFieldLength;
552

    
553
        // Field decimal count in Binary, indicating where the decimal is
554
        int myDecimalCount;
555
    }
556

    
557
        public byte getLanguageID() {
558
                return myLanguageID;
559
        }
560

    
561

    
562

    
563
        public static DbaseFileHeader createDbaseHeader(FeatureType featureType)
564
                        throws AttributeFeatureTypeNotSuportedException {
565
                DbaseFileHeader header = new DbaseFileHeader();
566
                Iterator iterator=featureType.iterator();
567
                // TODO header.myLanguageID = langId;
568
                while (iterator.hasNext()) {
569
                        FeatureAttributeDescriptor descriptor = (FeatureAttributeDescriptor) iterator.next();
570

    
571

    
572
                        int type = descriptor.getType();
573
                        String colName = descriptor.getName();
574

    
575
                        int fieldLen = descriptor.getSize(); // TODO aqu? el
576
                        // tama?o no es
577
                        // correcto hay que
578
                        // calcularlo, ahora
579
                        // mismo est? puesto
580
                        // a pi??n.
581
                        int decimales = descriptor.getPrecision();
582
                        if ((type==DataTypes.DOUBLE || type==DataTypes.FLOAT) && decimales==0){
583
                                decimales=1;
584
                        }
585

    
586
                        if (DataTypes.DOUBLE == type || DataTypes.FLOAT == type
587
                                        || DataTypes.INT == type || DataTypes.LONG == type) {
588
                                header.addColumn(colName, 'N', Math.min(fieldLen, 18),
589
                                                decimales);
590
                        } else if (DataTypes.DATE == type) {
591
                                header.addColumn(colName, 'D', fieldLen, 0);
592
                        } else if (DataTypes.BOOLEAN == type) {
593
                                header.addColumn(colName, 'L', 1, 0);
594
                        } else if (DataTypes.STRING == type) {
595
                                header.addColumn(colName, 'C', Math.min(254, fieldLen), 0);
596
                        }
597

    
598

    
599
                }
600
                return header;
601
        }
602
        /**
603
         * Write the header data to the DBF file.
604
         *
605
         * @param out
606
         *            A channel to write to. If you have an OutputStream you can
607
         *            obtain the correct channel by using
608
         *            java.nio.Channels.newChannel(OutputStream out).
609
         *
610
         * @throws IOException
611
         *             If errors occur.
612
         */
613
        public void writeHeader(FileChannel out) throws IOException {
614
                // take care of the annoying case where no records have been added...
615
                if (myHeaderLength == -1) {
616
                        myHeaderLength = MINIMUM_HEADER;
617
                }
618

    
619
                // Desde el principio
620
                out.position(0);
621

    
622
                ByteBuffer buffer = ByteBuffer.allocateDirect(myHeaderLength);
623
                buffer.order(ByteOrder.LITTLE_ENDIAN);
624

    
625
                // write the output file type.
626
                buffer.put(MAGIC);
627

    
628
                // write the date stuff
629
                Calendar c = Calendar.getInstance();
630
                c.setTime(new Date());
631
                buffer.put((byte) (c.get(Calendar.YEAR) % 100));
632
                buffer.put((byte) (c.get(Calendar.MONTH) + 1));
633
                buffer.put((byte) (c.get(Calendar.DAY_OF_MONTH)));
634

    
635
                // write the number of records in the datafile.
636
                buffer.putInt(myNumRecords);
637

    
638
                // write the length of the header structure.
639
                buffer.putShort((short) myHeaderLength);
640

    
641
                // write the length of a record
642
                buffer.putShort((short) myRecordLength);
643

    
644
                // // write the reserved bytes in the header
645
                // for (int i=0; i<20; i++) out.writeByteLE(0);
646
                buffer.position(buffer.position() + 20);
647

    
648
                // write all of the header records
649
                int tempOffset = 0;
650

    
651
                if (myFieldDescriptions != null) {
652
                        for (int i = 0; i < myFieldDescriptions.length; i++) {
653
                                // write the field name
654
                                for (int j = 0; j < 11; j++) {
655
                                        if (myFieldDescriptions[i].myFieldName.length() > j) {
656
                                                buffer.put((byte) myFieldDescriptions[i].myFieldName.charAt(j));
657
                                        } else {
658
                                                buffer.put((byte) 0);
659
                                        }
660
                                }
661

    
662
                                // write the field type
663
                                buffer.put((byte) myFieldDescriptions[i].myFieldType);
664

    
665
                                // // write the field data address, offset from the start of the
666
                                // record.
667
                                buffer.putInt(tempOffset);
668
                                tempOffset += myFieldDescriptions[i].myFieldLength;
669

    
670
                                // write the length of the field.
671
                                buffer.put((byte) myFieldDescriptions[i].myFieldLength);
672

    
673
                                // write the decimal count.
674
                                buffer.put((byte) myFieldDescriptions[i].myDecimalCount);
675

    
676
                                // write the reserved bytes.
677
                                // for (in j=0; jj<14; j++) out.writeByteLE(0);
678
                                buffer.position(buffer.position() + 14);
679
                        }
680
                }
681
                // write the end of the field definitions marker
682
                buffer.put((byte) 0x0D);
683

    
684
                buffer.position(0);
685

    
686
                int r = buffer.remaining();
687

    
688
                while ((r -= out.write(buffer)) > 0) {
689
                        ; // do nothing
690
                }
691
        }
692

    
693
        public String getCharsetName() {
694
                switch (getLanguageID()) {
695
                case 0x01:
696
                        return "US-ASCII";
697
                case 0x02:
698
                        return "ISO-8859-1";
699
                case 0x03:
700
                        return "windows-1252";
701
                case 0x04:
702
                        return "mac";
703
                case 0x64:
704
                        return "ISO-8859-1";
705
                case 0x65:
706
                        return "ISO-8859-1";
707
                case 0x66:
708
                        return "ISO-8859-1";
709
                case 0x67:
710
                        return "ISO-8859-1";
711
                case 0x68:
712
                        return "greek";
713
                case 0x69:
714
                        return "ISO-8859-1";
715
                case 0x6A:
716
                        return "greek";
717
                case 0x6B:
718
                        return "ISO-8859-1";
719

    
720
                default:
721
                        return "ISO-8859-1";
722
                }
723
        }
724

    
725
}