Revision 9524 branches/piloto3d/libraries/libFMap/src/com/iver/cit/gvsig/fmap/drivers/shp/DbaseFileHeaderNIO.java
DbaseFileHeaderNIO.java | ||
---|---|---|
80 | 80 |
import com.iver.utiles.bigfile.BigByteBuffer2; |
81 | 81 |
import com.vividsolutions.jts.geom.Geometry; |
82 | 82 |
|
83 |
|
|
84 | 83 |
/** |
85 | 84 |
* Class to represent the header of a Dbase III file. Creation date: (5/15/2001 |
86 | 85 |
* 5:15:30 PM) |
... | ... | |
91 | 90 |
|
92 | 91 |
// type of the file, must be 03h |
93 | 92 |
private static final byte MAGIC = 0x03; |
93 |
|
|
94 | 94 |
private static final int MINIMUM_HEADER = 33; |
95 | 95 |
|
96 | 96 |
// Date the file was last updated. |
97 | 97 |
private Date date = new Date(); |
98 |
|
|
98 | 99 |
private int recordCnt = 0; |
100 |
|
|
99 | 101 |
private int fieldCnt = 0; |
102 |
|
|
100 | 103 |
private int myFileType = 0; |
101 | 104 |
|
102 | 105 |
// set this to a default length of 1, which is enough for one "space" |
... | ... | |
106 | 109 |
// set this to a flagged value so if no fields are added before the write, |
107 | 110 |
// we know to adjust the headerLength to MINIMUM_HEADER |
108 | 111 |
private int headerLength = -1; |
112 |
|
|
109 | 113 |
private int largestFieldSize = 0; |
114 |
|
|
110 | 115 |
private Logger logger = Logger.getLogger("org.geotools.data.shapefile"); |
111 | 116 |
|
112 | 117 |
// collection of header records. |
... | ... | |
115 | 120 |
|
116 | 121 |
/** |
117 | 122 |
* Lee del buffer. |
118 |
* |
|
123 |
*
|
|
119 | 124 |
* @param buffer . |
120 | 125 |
* @param channel . |
121 |
* |
|
126 |
*
|
|
122 | 127 |
* @throws IOException . |
123 | 128 |
* @throws EOFException . |
124 | 129 |
*/ |
125 | 130 |
private void read(ByteBuffer buffer, ReadableByteChannel channel) |
126 |
throws IOException { |
|
131 |
throws IOException {
|
|
127 | 132 |
while (buffer.remaining() > 0) { |
128 | 133 |
if (channel.read(buffer) == -1) { |
129 | 134 |
throw new EOFException("Premature end of file"); |
... | ... | |
134 | 139 |
/** |
135 | 140 |
* Determine the most appropriate Java Class for representing the data in |
136 | 141 |
* the field. |
142 |
* |
|
137 | 143 |
* <PRE> |
138 |
* All packages are java.lang unless otherwise specified. |
|
139 |
* C (Character) -> String |
|
140 |
* N (Numeric) -> Integer or Double (depends on field's decimal count) |
|
141 |
* F (Floating) -> Double |
|
142 |
* L (Logical) -> Boolean |
|
143 |
* D (Date) -> java.util.Date |
|
144 |
* Unknown -> String |
|
144 |
* |
|
145 |
* All packages are java.lang unless otherwise specified. C (Character) -> |
|
146 |
* String N (Numeric) -> Integer or Double (depends on field's decimal |
|
147 |
* count) F (Floating) -> Double L (Logical) -> Boolean D (Date) -> |
|
148 |
* java.util.Date Unknown -> String |
|
149 |
* |
|
145 | 150 |
* </PRE> |
146 |
* |
|
147 |
* @param i The index of the field, from 0 to <CODE>getNumFields() -
|
|
148 |
* 1</CODE> .
|
|
149 |
* |
|
151 |
*
|
|
152 |
* @param i |
|
153 |
* The index of the field, from 0 to <CODE>getNumFields() - 1</CODE> .
|
|
154 |
*
|
|
150 | 155 |
* @return A Class which closely represents the dbase field type. |
151 | 156 |
*/ |
152 | 157 |
public Class getFieldClass(int i) { |
153 | 158 |
Class typeClass = null; |
154 | 159 |
|
155 | 160 |
switch (fields[i].fieldType) { |
156 |
case 'C':
|
|
157 |
typeClass = String.class;
|
|
161 |
case 'C': |
|
162 |
typeClass = String.class; |
|
158 | 163 |
|
159 |
break;
|
|
164 |
break; |
|
160 | 165 |
|
161 |
case 'N':
|
|
166 |
case 'N': |
|
162 | 167 |
|
163 |
if (fields[i].decimalCount == 0) {
|
|
164 |
typeClass = Integer.class;
|
|
165 |
} else {
|
|
166 |
typeClass = Double.class;
|
|
167 |
}
|
|
168 |
if (fields[i].decimalCount == 0) { |
|
169 |
typeClass = Integer.class; |
|
170 |
} else { |
|
171 |
typeClass = Double.class; |
|
172 |
} |
|
168 | 173 |
|
169 |
break;
|
|
174 |
break; |
|
170 | 175 |
|
171 |
case 'F':
|
|
172 |
typeClass = Double.class;
|
|
176 |
case 'F': |
|
177 |
typeClass = Double.class; |
|
173 | 178 |
|
174 |
break;
|
|
179 |
break; |
|
175 | 180 |
|
176 |
case 'L':
|
|
177 |
typeClass = Boolean.class;
|
|
181 |
case 'L': |
|
182 |
typeClass = Boolean.class; |
|
178 | 183 |
|
179 |
break;
|
|
184 |
break; |
|
180 | 185 |
|
181 |
case 'D':
|
|
182 |
typeClass = Date.class;
|
|
186 |
case 'D': |
|
187 |
typeClass = Date.class; |
|
183 | 188 |
|
184 |
break;
|
|
189 |
break; |
|
185 | 190 |
|
186 |
default:
|
|
187 |
typeClass = String.class;
|
|
191 |
default: |
|
192 |
typeClass = String.class; |
|
188 | 193 |
|
189 |
break;
|
|
194 |
break; |
|
190 | 195 |
} |
191 | 196 |
|
192 | 197 |
return typeClass; |
... | ... | |
194 | 199 |
|
195 | 200 |
/** |
196 | 201 |
* Add a column to this DbaseFileHeader. The type is one of (C N L or D) |
197 |
* character, number, logical(true/false), or date. The Field length is |
|
198 |
* the total length in bytes reserved for this column. The decimal count |
|
199 |
* only applies to numbers(N), and floating point values (F), and refers |
|
200 |
* to the number of characters to reserve after the decimal point. |
|
201 |
* <B>Don't expect miracles from this...</B> |
|
202 |
* character, number, logical(true/false), or date. The Field length is the |
|
203 |
* total length in bytes reserved for this column. The decimal count only |
|
204 |
* applies to numbers(N), and floating point values (F), and refers to the |
|
205 |
* number of characters to reserve after the decimal point. <B>Don't expect |
|
206 |
* miracles from this...</B> |
|
207 |
* |
|
202 | 208 |
* <PRE> |
203 |
* Field Type MaxLength |
|
204 |
* ---------- --------- |
|
205 |
* C 254 |
|
206 |
* D 8 |
|
207 |
* F 20 |
|
208 |
* N 18 |
|
209 |
* |
|
210 |
* Field Type MaxLength ---------- --------- C 254 D 8 F 20 N 18 |
|
211 |
* |
|
209 | 212 |
* </PRE> |
210 |
* |
|
211 |
* @param inFieldName The name of the new field, must be less than 10 |
|
212 |
* characters or it gets truncated. |
|
213 |
* @param inFieldType A character representing the dBase field, ( see above |
|
214 |
* ). Case insensitive. |
|
215 |
* @param inFieldLength The length of the field, in bytes ( see above ) |
|
216 |
* @param inDecimalCount For numeric fields, the number of decimal places |
|
217 |
* to track. |
|
213 |
* |
|
214 |
* @param inFieldName |
|
215 |
* The name of the new field, must be less than 10 characters or |
|
216 |
* it gets truncated. |
|
217 |
* @param inFieldType |
|
218 |
* A character representing the dBase field, ( see above ). Case |
|
219 |
* insensitive. |
|
220 |
* @param inFieldLength |
|
221 |
* The length of the field, in bytes ( see above ) |
|
222 |
* @param inDecimalCount |
|
223 |
* For numeric fields, the number of decimal places to track. |
|
218 | 224 |
*/ |
219 | 225 |
public void addColumn(String inFieldName, char inFieldType, |
220 |
int inFieldLength, int inDecimalCount) { |
|
221 |
/*if (inFieldLength <=0) {
|
|
222 |
throw new DbaseFileException("field length <= 0");
|
|
223 |
}
|
|
226 |
int inFieldLength, int inDecimalCount) {
|
|
227 |
/* |
|
228 |
* if (inFieldLength <=0) { throw new DbaseFileException("field length <=
|
|
229 |
* 0"); }
|
|
224 | 230 |
*/ |
225 | 231 |
if (fields == null) { |
226 | 232 |
fields = new DbaseField[0]; |
227 | 233 |
} |
228 | 234 |
|
229 |
int tempLength = 1; // the length is used for the offset, and there is a * for deleted as the first byte |
|
235 |
int tempLength = 1; // the length is used for the offset, and there is a |
|
236 |
// * for deleted as the first byte |
|
230 | 237 |
DbaseField[] tempFieldDescriptors = new DbaseField[fields.length + 1]; |
231 | 238 |
|
232 | 239 |
for (int i = 0; i < fields.length; i++) { |
... | ... | |
251 | 258 |
// Sorry folks. |
252 | 259 |
if (tempFieldName.length() > 10) { |
253 | 260 |
tempFieldName = tempFieldName.substring(0, 10); |
254 |
warn("FieldName " + inFieldName +
|
|
255 |
" is longer than 10 characters, truncating to " +
|
|
256 |
tempFieldName); |
|
261 |
warn("FieldName " + inFieldName |
|
262 |
+ " is longer than 10 characters, truncating to "
|
|
263 |
+ tempFieldName);
|
|
257 | 264 |
} |
258 | 265 |
|
259 | 266 |
tempFieldDescriptors[fields.length].fieldName = tempFieldName; |
... | ... | |
263 | 270 |
tempFieldDescriptors[fields.length].fieldType = 'C'; |
264 | 271 |
|
265 | 272 |
if (inFieldLength > 254) { |
266 |
warn("Field Length for " + inFieldName + " set to " + |
|
267 |
inFieldLength + |
|
268 |
" Which is longer than 254, not consistent with dbase III"); |
|
273 |
warn("Field Length for " |
|
274 |
+ inFieldName |
|
275 |
+ " set to " |
|
276 |
+ inFieldLength |
|
277 |
+ " Which is longer than 254, not consistent with dbase III"); |
|
269 | 278 |
} |
270 | 279 |
} else if ((inFieldType == 'S') || (inFieldType == 's')) { |
271 | 280 |
tempFieldDescriptors[fields.length].fieldType = 'C'; |
272 |
warn("Field type for " + inFieldName + |
|
273 |
" set to S which is flat out wrong people!, I am setting this to C, in the hopes you meant character."); |
|
281 |
warn("Field type for " |
|
282 |
+ inFieldName |
|
283 |
+ " set to S which is flat out wrong people!, I am setting this to C, in the hopes you meant character."); |
|
274 | 284 |
|
275 | 285 |
if (inFieldLength > 254) { |
276 |
warn("Field Length for " + inFieldName + " set to " + |
|
277 |
inFieldLength + |
|
278 |
" Which is longer than 254, not consistent with dbase III"); |
|
286 |
warn("Field Length for " |
|
287 |
+ inFieldName |
|
288 |
+ " set to " |
|
289 |
+ inFieldLength |
|
290 |
+ " Which is longer than 254, not consistent with dbase III"); |
|
279 | 291 |
} |
280 | 292 |
|
281 | 293 |
tempFieldDescriptors[fields.length].fieldLength = 8; |
... | ... | |
283 | 295 |
tempFieldDescriptors[fields.length].fieldType = 'D'; |
284 | 296 |
|
285 | 297 |
if (inFieldLength != 8) { |
286 |
warn("Field Length for " + inFieldName + " set to " +
|
|
287 |
inFieldLength + " Setting to 8 digets YYYYMMDD"); |
|
298 |
warn("Field Length for " + inFieldName + " set to " |
|
299 |
+ inFieldLength + " Setting to 8 digets YYYYMMDD");
|
|
288 | 300 |
} |
289 | 301 |
|
290 | 302 |
tempFieldDescriptors[fields.length].fieldLength = 8; |
... | ... | |
292 | 304 |
tempFieldDescriptors[fields.length].fieldType = 'F'; |
293 | 305 |
|
294 | 306 |
if (inFieldLength > 20) { |
295 |
warn("Field Length for " + inFieldName + " set to " + |
|
296 |
inFieldLength + |
|
297 |
" Preserving length, but should be set to Max of 20 not valid for dbase IV, and UP specification, not present in dbaseIII."); |
|
307 |
warn("Field Length for " |
|
308 |
+ inFieldName |
|
309 |
+ " set to " |
|
310 |
+ inFieldLength |
|
311 |
+ " Preserving length, but should be set to Max of 20 not valid for dbase IV, and UP specification, not present in dbaseIII."); |
|
298 | 312 |
} |
299 | 313 |
} else if ((inFieldType == 'N') || (inFieldType == 'n')) { |
300 | 314 |
tempFieldDescriptors[fields.length].fieldType = 'N'; |
301 | 315 |
|
302 | 316 |
if (inFieldLength > 18) { |
303 |
warn("Field Length for " + inFieldName + " set to " + |
|
304 |
inFieldLength + |
|
305 |
" Preserving length, but should be set to Max of 18 for dbase III specification."); |
|
317 |
warn("Field Length for " |
|
318 |
+ inFieldName |
|
319 |
+ " set to " |
|
320 |
+ inFieldLength |
|
321 |
+ " Preserving length, but should be set to Max of 18 for dbase III specification."); |
|
306 | 322 |
} |
307 | 323 |
|
308 | 324 |
if (inDecimalCount < 0) { |
309 |
warn("Field Decimal Position for " + inFieldName + " set to " +
|
|
310 |
inDecimalCount +
|
|
311 |
" Setting to 0 no decimal data will be saved."); |
|
325 |
warn("Field Decimal Position for " + inFieldName + " set to " |
|
326 |
+ inDecimalCount
|
|
327 |
+ " Setting to 0 no decimal data will be saved.");
|
|
312 | 328 |
tempFieldDescriptors[fields.length].decimalCount = 0; |
313 | 329 |
} |
314 | 330 |
|
315 | 331 |
if (inDecimalCount > (inFieldLength - 1)) { |
316 |
warn("Field Decimal Position for " + inFieldName + " set to " + |
|
317 |
inDecimalCount + " Setting to " + (inFieldLength - 1) + |
|
318 |
" no non decimal data will be saved."); |
|
319 |
tempFieldDescriptors[fields.length].decimalCount = inFieldLength - |
|
320 |
1; |
|
332 |
warn("Field Decimal Position for " + inFieldName + " set to " |
|
333 |
+ inDecimalCount + " Setting to " + (inFieldLength - 1) |
|
334 |
+ " no non decimal data will be saved."); |
|
335 |
tempFieldDescriptors[fields.length].decimalCount = inFieldLength - 1; |
|
321 | 336 |
} |
322 | 337 |
} else if ((inFieldType == 'L') || (inFieldType == 'l')) { |
323 | 338 |
tempFieldDescriptors[fields.length].fieldType = 'L'; |
324 | 339 |
|
325 | 340 |
if (inFieldLength != 1) { |
326 |
warn("Field Length for " + inFieldName + " set to " +
|
|
327 |
inFieldLength +
|
|
328 |
" Setting to length of 1 for logical fields."); |
|
341 |
warn("Field Length for " + inFieldName + " set to " |
|
342 |
+ inFieldLength
|
|
343 |
+ " Setting to length of 1 for logical fields.");
|
|
329 | 344 |
} |
330 | 345 |
|
331 | 346 |
tempFieldDescriptors[fields.length].fieldLength = 1; |
332 | 347 |
} else { |
333 |
//throw new DbaseFileException("Undefined field type "+inFieldType + " For column "+inFieldName); |
|
348 |
// throw new DbaseFileException("Undefined field type "+inFieldType |
|
349 |
// + " For column "+inFieldName); |
|
334 | 350 |
} |
335 | 351 |
|
336 | 352 |
// the length of a record |
337 |
tempLength = tempLength +
|
|
338 |
tempFieldDescriptors[fields.length].fieldLength; |
|
353 |
tempLength = tempLength |
|
354 |
+ tempFieldDescriptors[fields.length].fieldLength;
|
|
339 | 355 |
|
340 | 356 |
// set the new fields. |
341 | 357 |
fields = tempFieldDescriptors; |
... | ... | |
346 | 362 |
|
347 | 363 |
/** |
348 | 364 |
* Remove a column from this DbaseFileHeader. |
349 |
* |
|
350 |
* @param inFieldName The name of the field, will ignore case and trim. |
|
351 |
* |
|
365 |
* |
|
366 |
* @param inFieldName |
|
367 |
* The name of the field, will ignore case and trim. |
|
368 |
* |
|
352 | 369 |
* @return index of the removed column, -1 if no found |
353 |
* |
|
354 |
* @todo This is really ugly, don't know who wrote it, but it needs |
|
355 |
* fixin... |
|
370 |
* |
|
371 |
* @todo This is really ugly, don't know who wrote it, but it needs fixin... |
|
356 | 372 |
*/ |
357 | 373 |
public int removeColumn(String inFieldName) { |
358 | 374 |
int retCol = -1; |
... | ... | |
364 | 380 |
// if this is the last field and we still haven't found the |
365 | 381 |
// named field |
366 | 382 |
if ((i == j) && (i == (fields.length - 1))) { |
367 |
System.err.println("Could not find a field named '" +
|
|
368 |
inFieldName + "' for removal"); |
|
383 |
System.err.println("Could not find a field named '" |
|
384 |
+ inFieldName + "' for removal");
|
|
369 | 385 |
|
370 | 386 |
return retCol; |
371 | 387 |
} |
... | ... | |
391 | 407 |
|
392 | 408 |
/** |
393 | 409 |
* DOCUMENT ME! |
394 |
* |
|
395 |
* @param inWarn DOCUMENT ME! |
|
396 |
* |
|
410 |
* |
|
411 |
* @param inWarn |
|
412 |
* DOCUMENT ME! |
|
413 |
* |
|
397 | 414 |
* @todo addProgessListener handling |
398 | 415 |
*/ |
399 | 416 |
private void warn(String inWarn) { |
... | ... | |
406 | 423 |
|
407 | 424 |
/** |
408 | 425 |
* Returns the field length in bytes. |
409 |
* |
|
410 |
* @param inIndex The field index. |
|
411 |
* |
|
426 |
* |
|
427 |
* @param inIndex |
|
428 |
* The field index. |
|
429 |
* |
|
412 | 430 |
* @return The length in bytes. |
413 | 431 |
*/ |
414 | 432 |
public int getFieldLength(int inIndex) { |
... | ... | |
419 | 437 |
|
420 | 438 |
/** |
421 | 439 |
* Get the decimal count of this field. |
422 |
* |
|
423 |
* @param inIndex The field index. |
|
424 |
* |
|
440 |
* |
|
441 |
* @param inIndex |
|
442 |
* The field index. |
|
443 |
* |
|
425 | 444 |
* @return The decimal count. |
426 | 445 |
*/ |
427 | 446 |
public int getFieldDecimalCount(int inIndex) { |
... | ... | |
432 | 451 |
|
433 | 452 |
/** |
434 | 453 |
* Get the field name. |
435 |
* |
|
436 |
* @param inIndex The field index. |
|
437 |
* |
|
454 |
* |
|
455 |
* @param inIndex |
|
456 |
* The field index. |
|
457 |
* |
|
438 | 458 |
* @return The name of the field. |
439 | 459 |
*/ |
440 | 460 |
public String getFieldName(int inIndex) { |
... | ... | |
445 | 465 |
|
446 | 466 |
/** |
447 | 467 |
* Get the character class of the field. |
448 |
* |
|
449 |
* @param inIndex The field index. |
|
450 |
* |
|
468 |
* |
|
469 |
* @param inIndex |
|
470 |
* The field index. |
|
471 |
* |
|
451 | 472 |
* @return The dbase character representing this field. |
452 | 473 |
*/ |
453 | 474 |
public char getFieldType(int inIndex) { |
... | ... | |
456 | 477 |
|
457 | 478 |
/** |
458 | 479 |
* Get the date this file was last updated. |
459 |
* |
|
480 |
*
|
|
460 | 481 |
* @return The Date last modified. |
461 | 482 |
*/ |
462 | 483 |
public Date getLastUpdateDate() { |
... | ... | |
465 | 486 |
|
466 | 487 |
/** |
467 | 488 |
* Return the number of fields in the records. |
468 |
* |
|
489 |
*
|
|
469 | 490 |
* @return The number of fields in this table. |
470 | 491 |
*/ |
471 | 492 |
public int getNumFields() { |
... | ... | |
476 | 497 |
|
477 | 498 |
/** |
478 | 499 |
* Return the number of records in the file |
479 |
* |
|
500 |
*
|
|
480 | 501 |
* @return The number of records in this table. |
481 | 502 |
*/ |
482 | 503 |
public int getNumRecords() { |
... | ... | |
485 | 506 |
|
486 | 507 |
/** |
487 | 508 |
* Get the length of the records in bytes. |
488 |
* |
|
509 |
*
|
|
489 | 510 |
* @return The number of bytes per record. |
490 | 511 |
*/ |
491 | 512 |
public int getRecordLength() { |
... | ... | |
494 | 515 |
|
495 | 516 |
/** |
496 | 517 |
* Get the length of the header |
497 |
* |
|
518 |
*
|
|
498 | 519 |
* @return The length of the header in bytes. |
499 | 520 |
*/ |
500 | 521 |
public int getHeaderLength() { |
... | ... | |
503 | 524 |
|
504 | 525 |
/** |
505 | 526 |
* Read the header data from the DBF file. |
506 |
* |
|
507 |
* @param in DOCUMENT ME! |
|
508 |
* |
|
509 |
* @throws IOException DOCUMENT ME! |
|
527 |
* |
|
528 |
* @param in |
|
529 |
* DOCUMENT ME! |
|
530 |
* |
|
531 |
* @throws IOException |
|
532 |
* DOCUMENT ME! |
|
510 | 533 |
*/ |
511 | 534 |
public void readHeader(BigByteBuffer2 in) throws IOException { |
512 | 535 |
// type of file. |
513 | 536 |
myFileType = in.get(); |
514 | 537 |
|
515 | 538 |
if (myFileType != 0x03) { |
516 |
throw new IOException("Unsupported DBF file Type " +
|
|
517 |
Integer.toHexString(myFileType)); |
|
539 |
throw new IOException("Unsupported DBF file Type " |
|
540 |
+ Integer.toHexString(myFileType));
|
|
518 | 541 |
} |
519 | 542 |
|
520 | 543 |
// parse the update date information. |
... | ... | |
545 | 568 |
in.position(in.position() + 20); |
546 | 569 |
|
547 | 570 |
// calculate the number of Fields in the header |
548 |
fieldCnt = (headerLength - FILE_DESCRIPTOR_SIZE - 1) / FILE_DESCRIPTOR_SIZE; |
|
571 |
fieldCnt = (headerLength - FILE_DESCRIPTOR_SIZE - 1) |
|
572 |
/ FILE_DESCRIPTOR_SIZE; |
|
549 | 573 |
|
550 | 574 |
// read all of the header records |
551 | 575 |
fields = new DbaseField[fieldCnt]; |
... | ... | |
586 | 610 |
|
587 | 611 |
/** |
588 | 612 |
* Get the largest field size of this table. |
589 |
* |
|
613 |
*
|
|
590 | 614 |
* @return The largt field size iiin bytes. |
591 | 615 |
*/ |
592 | 616 |
public int getLargestFieldSize() { |
... | ... | |
595 | 619 |
|
596 | 620 |
/** |
597 | 621 |
* Set the number of records in the file |
598 |
* |
|
599 |
* @param inNumRecords The number of records. |
|
622 |
* |
|
623 |
* @param inNumRecords |
|
624 |
* The number of records. |
|
600 | 625 |
*/ |
601 | 626 |
public void setNumRecords(int inNumRecords) { |
602 | 627 |
recordCnt = inNumRecords; |
... | ... | |
604 | 629 |
|
605 | 630 |
/** |
606 | 631 |
* Write the header data to the DBF file. |
607 |
* |
|
608 |
* @param out A channel to write to. If you have an OutputStream you can |
|
609 |
* obtain the correct channel by using |
|
610 |
* java.nio.Channels.newChannel(OutputStream out). |
|
611 |
* |
|
612 |
* @throws IOException If errors occur. |
|
632 |
* |
|
633 |
* @param out |
|
634 |
* A channel to write to. If you have an OutputStream you can |
|
635 |
* obtain the correct channel by using |
|
636 |
* java.nio.Channels.newChannel(OutputStream out). |
|
637 |
* |
|
638 |
* @throws IOException |
|
639 |
* If errors occur. |
|
613 | 640 |
*/ |
614 | 641 |
public void writeHeader(FileChannel out) throws IOException { |
615 | 642 |
// take care of the annoying case where no records have been added... |
... | ... | |
619 | 646 |
|
620 | 647 |
// Desde el principio |
621 | 648 |
out.position(0); |
622 |
|
|
649 |
|
|
623 | 650 |
ByteBuffer buffer = ByteBuffer.allocateDirect(headerLength); |
624 | 651 |
buffer.order(ByteOrder.LITTLE_ENDIAN); |
625 | 652 |
|
... | ... | |
642 | 669 |
// write the length of a record |
643 | 670 |
buffer.putShort((short) recordLength); |
644 | 671 |
|
645 |
// // write the reserved bytes in the header
|
|
646 |
// for (int i=0; i<20; i++) out.writeByteLE(0);
|
|
672 |
// // write the reserved bytes in the header |
|
673 |
// for (int i=0; i<20; i++) out.writeByteLE(0); |
|
647 | 674 |
buffer.position(buffer.position() + 20); |
648 | 675 |
|
649 | 676 |
// write all of the header records |
650 | 677 |
int tempOffset = 0; |
651 | 678 |
|
652 |
if (fields != null) |
|
653 |
{ |
|
679 |
if (fields != null) { |
|
654 | 680 |
for (int i = 0; i < fields.length; i++) { |
655 | 681 |
// write the field name |
656 | 682 |
for (int j = 0; j < 11; j++) { |
... | ... | |
660 | 686 |
buffer.put((byte) 0); |
661 | 687 |
} |
662 | 688 |
} |
663 |
|
|
689 |
|
|
664 | 690 |
// write the field type |
665 | 691 |
buffer.put((byte) fields[i].fieldType); |
666 |
|
|
667 |
// // write the field data address, offset from the start of the record. |
|
692 |
|
|
693 |
// // write the field data address, offset from the start of the |
|
694 |
// record. |
|
668 | 695 |
buffer.putInt(tempOffset); |
669 | 696 |
tempOffset += fields[i].fieldLength; |
670 |
|
|
697 |
|
|
671 | 698 |
// write the length of the field. |
672 | 699 |
buffer.put((byte) fields[i].fieldLength); |
673 |
|
|
700 |
|
|
674 | 701 |
// write the decimal count. |
675 | 702 |
buffer.put((byte) fields[i].decimalCount); |
676 |
|
|
703 |
|
|
677 | 704 |
// write the reserved bytes. |
678 |
//for (in j=0; jj<14; j++) out.writeByteLE(0); |
|
705 |
// for (in j=0; jj<14; j++) out.writeByteLE(0);
|
|
679 | 706 |
buffer.position(buffer.position() + 14); |
680 | 707 |
} |
681 | 708 |
} |
... | ... | |
693 | 720 |
|
694 | 721 |
/** |
695 | 722 |
* Get a simple representation of this header. |
696 |
* |
|
723 |
*
|
|
697 | 724 |
* @return A String representing the state of the header. |
698 | 725 |
*/ |
699 | 726 |
public String toString() { |
... | ... | |
701 | 728 |
|
702 | 729 |
for (int i = 0, ii = fields.length; i < ii; i++) { |
703 | 730 |
DbaseField f = fields[i]; |
704 |
fs.append(f.fieldName + " " + f.fieldType + " " + f.fieldLength +
|
|
705 |
" " + f.decimalCount + " " + f.fieldDataAddress + "\n"); |
|
731 |
fs.append(f.fieldName + " " + f.fieldType + " " + f.fieldLength |
|
732 |
+ " " + f.decimalCount + " " + f.fieldDataAddress + "\n");
|
|
706 | 733 |
} |
707 | 734 |
|
708 |
return "DB3 Header\n" + "Date : " + date + "\n" + "Records : " +
|
|
709 |
recordCnt + "\n" + "Fields : " + fieldCnt + "\n" + fs; |
|
735 |
return "DB3 Header\n" + "Date : " + date + "\n" + "Records : " |
|
736 |
+ recordCnt + "\n" + "Fields : " + fieldCnt + "\n" + fs;
|
|
710 | 737 |
} |
711 | 738 |
|
712 | 739 |
/** |
713 | 740 |
* Crea un DbaseFile. |
714 |
* |
|
741 |
*
|
|
715 | 742 |
* @return DbaseFileHeaderNIO |
716 |
* |
|
743 |
*
|
|
717 | 744 |
* @throws IOException . |
718 | 745 |
*/ |
719 |
public static DbaseFileHeaderNIO createNewDbaseHeader() |
|
720 |
throws IOException { |
|
746 |
public static DbaseFileHeaderNIO createNewDbaseHeader() throws IOException { |
|
721 | 747 |
DbaseFileHeaderNIO header = new DbaseFileHeaderNIO(); |
722 | 748 |
|
723 | 749 |
for (int i = 0, ii = 1; i < ii; i++) { |
724 |
//AttributeType type = featureType.getAttributeType(i); |
|
750 |
// AttributeType type = featureType.getAttributeType(i);
|
|
725 | 751 |
Class colType = Integer.class; |
726 | 752 |
String colName = "ID"; |
727 | 753 |
int fieldLen = 10; |
... | ... | |
731 | 757 |
} |
732 | 758 |
|
733 | 759 |
// @todo respect field length |
734 |
if ((colType == Integer.class) || (colType == Short.class) ||
|
|
735 |
(colType == Byte.class)) { |
|
760 |
if ((colType == Integer.class) || (colType == Short.class) |
|
761 |
|| (colType == Byte.class)) {
|
|
736 | 762 |
header.addColumn(colName, 'N', Math.min(fieldLen, 10), 0); |
737 | 763 |
} else if (colType == Long.class) { |
738 | 764 |
header.addColumn(colName, 'N', Math.min(fieldLen, 19), 0); |
739 |
} else if ((colType == Double.class) || (colType == Float.class) ||
|
|
740 |
(colType == Number.class)) { |
|
765 |
} else if ((colType == Double.class) || (colType == Float.class) |
|
766 |
|| (colType == Number.class)) {
|
|
741 | 767 |
int l = Math.min(fieldLen, 33); |
742 | 768 |
int d = Math.max(l - 2, 0); |
743 | 769 |
header.addColumn(colName, 'N', l, d); |
... | ... | |
759 | 785 |
return header; |
760 | 786 |
} |
761 | 787 |
|
762 |
public static DbaseFileHeaderNIO createDbaseHeader(DataSource ds) |
|
763 |
throws IOException { |
|
764 |
try { |
|
765 |
int[] fieldTypes = new int[ds.getFieldCount()]; |
|
766 |
int[] fieldLength = new int[fieldTypes.length]; |
|
767 |
for (int i = 0; i < fieldTypes.length; i++) { |
|
768 |
fieldTypes[i] = ds.getFieldType(i); |
|
769 |
fieldLength[i] = ds.getFieldWidth(i); |
|
770 |
} |
|
771 |
|
|
772 |
return createDbaseHeader(ds.getFieldNames(), fieldTypes, fieldLength); |
|
773 |
} catch (DriverException e) { |
|
774 |
// TODO Auto-generated catch block |
|
775 |
e.printStackTrace(); |
|
776 |
return null; |
|
777 |
} |
|
778 |
} |
|
788 |
public static DbaseFileHeaderNIO createDbaseHeader(DataSource ds) |
|
789 |
throws IOException { |
|
790 |
try { |
|
791 |
int[] fieldTypes = new int[ds.getFieldCount()]; |
|
792 |
int[] fieldLength = new int[fieldTypes.length]; |
|
793 |
for (int i = 0; i < fieldTypes.length; i++) { |
|
794 |
fieldTypes[i] = ds.getFieldType(i); |
|
795 |
fieldLength[i] = ds.getFieldWidth(i); |
|
796 |
} |
|
779 | 797 |
|
798 |
return createDbaseHeader(ds.getFieldNames(), fieldTypes, |
|
799 |
fieldLength); |
|
800 |
} catch (DriverException e) { |
|
801 |
// TODO Auto-generated catch block |
|
802 |
e.printStackTrace(); |
|
803 |
return null; |
|
804 |
} |
|
805 |
} |
|
806 |
|
|
780 | 807 |
/** |
781 | 808 |
* DOCUMENT ME! |
782 |
* |
|
783 |
* @param sds DOCUMENT ME! |
|
784 |
* |
|
809 |
* |
|
810 |
* @param sds |
|
811 |
* DOCUMENT ME! |
|
812 |
* |
|
785 | 813 |
* @return DOCUMENT ME! |
786 |
* |
|
787 |
* @throws IOException DOCUMENT ME! |
|
814 |
* |
|
815 |
* @throws IOException |
|
816 |
* DOCUMENT ME! |
|
788 | 817 |
*/ |
789 |
public static DbaseFileHeaderNIO createDbaseHeader(String[] fieldNames, int[] fieldTypes, int[] fieldLength)
|
|
790 |
throws IOException { |
|
818 |
public static DbaseFileHeaderNIO createDbaseHeader(String[] fieldNames, |
|
819 |
int[] fieldTypes, int[] fieldLength) throws IOException {
|
|
791 | 820 |
DbaseFileHeaderNIO header = new DbaseFileHeaderNIO(); |
792 | 821 |
|
793 |
for (int i = 0, ii = fieldNames.length; i < ii; i++) {
|
|
822 |
for (int i = 0, ii = fieldNames.length; i < ii; i++) { |
|
794 | 823 |
|
795 |
int type = fieldTypes[i];
|
|
796 |
String colName = fieldNames[i];
|
|
824 |
int type = fieldTypes[i]; |
|
825 |
String colName = fieldNames[i]; |
|
797 | 826 |
|
798 |
///int fieldLen = ((DBFDriver)sds.getDriver()).getFieldLength(i); |
|
799 |
int fieldLen = fieldLength[i]; //TODO aqu? el tama?o no es correcto hay que calcularlo, ahora mismo est? puesto a pi??n. |
|
800 |
int decimales = 5; |
|
827 |
// /int fieldLen = ((DBFDriver)sds.getDriver()).getFieldLength(i); |
|
828 |
int fieldLen = fieldLength[i]; // TODO aqu? el tama?o no es |
|
829 |
// correcto hay que calcularlo, |
|
830 |
// ahora mismo est? puesto a pi??n. |
|
831 |
int decimales = 5; |
|
801 | 832 |
|
802 |
// if (fieldLen <= 0) { |
|
803 |
// fieldLen = 255; |
|
804 |
// } |
|
805 |
//TODO [AZABALA] HE INTENTADO CREAR UN TIPO Types.BIGINT y |
|
806 |
//ha petado (por eso lo a?ado) |
|
807 |
if ((type == Types.DOUBLE) || |
|
808 |
(type == Types.FLOAT) || |
|
809 |
(type == Types.INTEGER) || |
|
810 |
(type == Types.BIGINT)) |
|
811 |
|
|
812 |
header.addColumn(colName, 'N', Math.min(fieldLen, 18), |
|
813 |
decimales); |
|
814 |
if (type == Types.DATE) |
|
815 |
header.addColumn(colName, 'D', fieldLen, 0); |
|
816 |
if ((type == Types.BIT) || |
|
817 |
(type == Types.BOOLEAN)) |
|
818 |
header.addColumn(colName, 'L', 1, 0); |
|
819 |
if ((type == Types.VARCHAR) || |
|
820 |
(type == Types.CHAR) || |
|
821 |
(type == Types.LONGVARCHAR)) |
|
822 |
header.addColumn(colName, 'C', Math.min(254, fieldLen), |
|
823 |
0); |
|
824 |
} |
|
833 |
// if (fieldLen <= 0) { |
|
834 |
// fieldLen = 255; |
|
835 |
// } |
|
836 |
// TODO [AZABALA] HE INTENTADO CREAR UN TIPO Types.BIGINT y |
|
837 |
// ha petado (por eso lo a?ado) |
|
838 |
if ((type == Types.DOUBLE) || (type == Types.FLOAT) |
|
839 |
|| (type == Types.INTEGER) || (type == Types.BIGINT)) |
|
825 | 840 |
|
841 |
header.addColumn(colName, 'N', Math.min(fieldLen, 18), |
|
842 |
decimales); |
|
843 |
if (type == Types.DATE) |
|
844 |
header.addColumn(colName, 'D', fieldLen, 0); |
|
845 |
if ((type == Types.BIT) || (type == Types.BOOLEAN)) |
|
846 |
header.addColumn(colName, 'L', 1, 0); |
|
847 |
if ((type == Types.VARCHAR) || (type == Types.CHAR) |
|
848 |
|| (type == Types.LONGVARCHAR)) |
|
849 |
header.addColumn(colName, 'C', Math.min(254, fieldLen), 0); |
|
850 |
} |
|
851 |
|
|
826 | 852 |
return header; |
827 | 853 |
} |
828 | 854 |
|
829 |
|
|
830 | 855 |
/** |
831 | 856 |
* Class for holding the information assicated with a record. |
832 | 857 |
*/ |
... | ... | |
847 | 872 |
int decimalCount; |
848 | 873 |
} |
849 | 874 |
|
850 |
|
|
851 |
public static DbaseFileHeaderNIO createDbaseHeader(FieldDescription[] fieldsDesc) {
|
|
875 |
public static DbaseFileHeaderNIO createDbaseHeader( |
|
876 |
FieldDescription[] fieldsDesc) {
|
|
852 | 877 |
DbaseFileHeaderNIO header = new DbaseFileHeaderNIO(); |
853 | 878 |
|
854 | 879 |
for (int i = 0, ii = fieldsDesc.length; i < ii; i++) { |
... | ... | |
856 | 881 |
int type = fieldsDesc[i].getFieldType(); |
857 | 882 |
String colName = fieldsDesc[i].getFieldName(); |
858 | 883 |
|
859 |
int fieldLen = fieldsDesc[i].getFieldLength(); //TODO aqu? el tama?o no es correcto hay que calcularlo, ahora mismo est? puesto a pi??n. |
|
884 |
int fieldLen = fieldsDesc[i].getFieldLength(); // TODO aqu? el |
|
885 |
// tama?o no es |
|
886 |
// correcto hay que |
|
887 |
// calcularlo, ahora |
|
888 |
// mismo est? puesto |
|
889 |
// a pi??n. |
|
860 | 890 |
int decimales = fieldsDesc[i].getFieldDecimalCount(); |
861 | 891 |
|
862 |
if ((type == Types.DOUBLE) || |
|
863 |
(type == Types.FLOAT) || |
|
864 |
(type == Types.INTEGER)|| |
|
865 |
(type == Types.BIGINT)) |
|
866 |
|
|
867 |
header.addColumn(colName, 'N', Math.min(fieldLen, 18), |
|
892 |
switch (type) { |
|
893 |
case Types.DOUBLE: |
|
894 |
case Types.FLOAT: |
|
895 |
case Types.INTEGER: |
|
896 |
case Types.BIGINT: |
|
897 |
case Types.SMALLINT: |
|
898 |
header.addColumn(colName, 'N', Math.min(fieldLen, 18), |
|
868 | 899 |
decimales); |
869 |
if (type == Types.DATE) |
|
870 |
header.addColumn(colName, 'D', fieldLen, 0); |
|
871 |
if ((type == Types.BIT) || |
|
872 |
(type == Types.BOOLEAN)) |
|
873 |
header.addColumn(colName, 'L', 1, 0); |
|
874 |
if ((type == Types.VARCHAR) || |
|
875 |
(type == Types.CHAR) || |
|
876 |
(type == Types.LONGVARCHAR)) |
|
877 |
header.addColumn(colName, 'C', Math.min(254, fieldLen), |
|
878 |
0); |
|
900 |
break; |
|
901 |
case Types.DATE: |
|
902 |
header.addColumn(colName, 'D', fieldLen, 0); |
|
903 |
break; |
|
904 |
case Types.BIT: |
|
905 |
case Types.BOOLEAN: |
|
906 |
header.addColumn(colName, 'L', 1, 0); |
|
907 |
break; |
|
908 |
case Types.VARCHAR: |
|
909 |
case Types.CHAR: |
|
910 |
case Types.LONGVARCHAR: |
|
911 |
header.addColumn(colName, 'C', Math.min(254, fieldLen), 0); |
|
912 |
break; |
|
913 |
default: |
|
914 |
throw new RuntimeException("Field type " + type + " not supported in DBF writer"); |
|
915 |
|
|
879 | 916 |
} |
917 |
} // for |
|
880 | 918 |
|
881 |
return header; |
|
919 |
return header;
|
|
882 | 920 |
|
883 | 921 |
} |
884 | 922 |
|
Also available in: Unified diff