001: package org.geotools.dbffile;
002:
003: import java.io.*;
004: import java.math.BigDecimal;
005: import java.util.*;
006:
007: import org.geotools.misc.FormatedString;
008:
009: import com.vividsolutions.jump.io.EndianDataOutputStream;
010:
011: /** a class for writing dbf files
012: * @author Ian Turton
013: * modified by Michaël MICHAUD on 3 nov. 2004
014: */
015:
016: public class DbfFileWriter implements DbfConsts {
017:
018: private final static boolean DEBUG = false;
019:
020: private final static String DBC = "DbFW>";
021:
022: int NoFields = 1;
023:
024: int NoRecs = 0;
025:
026: int recLength = 0;
027:
028: DbfFieldDef fields[];
029:
030: EndianDataOutputStream ls;
031:
032: private boolean header = false;
033:
034: public DbfFileWriter(String file) throws IOException {
035: if (DEBUG)
036: System.out
037: .println("---->uk.ac.leeds.ccg.dbffile.DbfFileWriter constructed. Will identify itself as "
038: + DBC);
039: ls = new EndianDataOutputStream(new BufferedOutputStream(
040: new FileOutputStream(file)));
041: }
042:
043: public void writeHeader(DbfFieldDef f[], int nrecs)
044: throws IOException {
045:
046: NoFields = f.length;
047: NoRecs = nrecs;
048: fields = new DbfFieldDef[NoFields];
049: for (int i = 0; i < NoFields; i++) {
050: fields[i] = f[i];
051: }
052: ls.writeByteLE(3); // ID - dbase III with out memo
053:
054: // sort out the date
055: Calendar calendar = new GregorianCalendar();
056: Date trialTime = new Date();
057: calendar.setTime(trialTime);
058: ls.writeByteLE(calendar.get(Calendar.YEAR) - DBF_CENTURY);
059: ls.writeByteLE(calendar.get(Calendar.MONTH) + 1); // month is 0-indexed
060: ls.writeByteLE(calendar.get(Calendar.DAY_OF_MONTH));
061:
062: int dataOffset = 32 * NoFields + 32 + 1;
063: for (int i = 0; i < NoFields; i++) {
064: recLength += fields[i].fieldlen;
065: }
066:
067: recLength++; // delete flag
068: if (DEBUG)
069: System.out.println(DBC + "rec length " + recLength);
070: ls.writeIntLE(NoRecs);
071: ls.writeShortLE(dataOffset); // length of header
072: ls.writeShortLE(recLength);
073:
074: for (int i = 0; i < 20; i++)
075: ls.writeByteLE(0); // 20 bytes of junk!
076:
077: // field descriptions
078: for (int i = 0; i < NoFields; i++) {
079: ls.writeBytesLE(fields[i].fieldname.toString());
080: ls.writeByteLE(fields[i].fieldtype);
081: for (int j = 0; j < 4; j++)
082: ls.writeByteLE(0); // junk
083: ls.writeByteLE(fields[i].fieldlen);
084: ls.writeByteLE(fields[i].fieldnumdec);
085: for (int j = 0; j < 14; j++)
086: ls.writeByteLE(0); // more junk
087: }
088: ls.writeByteLE(0xd);
089: header = true;
090: }
091:
092: public void writeRecords(Vector[] recs) throws DbfFileException,
093: IOException {
094: if (!header) {
095: throw (new DbfFileException(
096: "Must write header before records"));
097: }
098: int i = 0;
099: try {
100: if (DEBUG)
101: System.out.println(DBC + ":writeRecords writing "
102: + recs.length + " records");
103: for (i = 0; i < recs.length; i++) {
104: if (recs[i].size() != NoFields)
105: throw new DbfFileException(
106: "wrong number of records in " + i
107: + "th record " + recs[i].size()
108: + " expected " + NoFields);
109: writeRecord(recs[i]);
110: }
111: } catch (DbfFileException e) {
112: throw new DbfFileException(DBC + "at rec " + i + "\n" + e);
113: }
114: }
115:
116: public void writeRecord(Vector rec) throws DbfFileException,
117: IOException {
118: if (!header) {
119: throw (new DbfFileException(DBC
120: + "Must write header before records"));
121: }
122:
123: if (rec.size() != NoFields)
124: throw new DbfFileException(DBC + "wrong number of fields "
125: + rec.size() + " expected " + NoFields);
126: String s;
127: ls.writeByteLE(' ');
128: int len;
129: StringBuffer tmps;
130: for (int i = 0; i < NoFields; i++) {
131: len = fields[i].fieldlen;
132: Object o = rec.elementAt(i);
133: switch (fields[i].fieldtype) {
134: case 'C':
135: case 'c':
136: case 'D': //Added by [Jon Aquino]
137: //case 'L': moved to the end by Michaël MICHAUD
138: case 'M':
139: case 'G':
140: //chars
141: String ss = (String) o;
142: while (ss.length() < fields[i].fieldlen) {
143: //need to fill it with ' ' chars
144: //this should converge quickly
145: ss = ss
146: + " ";
147: }
148: tmps = new StringBuffer(ss);
149: tmps.setLength(fields[i].fieldlen);
150: ls.writeBytesLE(tmps.toString());
151: break;
152: case 'N':
153: case 'n':
154: // int?
155: String fs = "";
156: if (fields[i].fieldnumdec == 0) {
157: if (o instanceof Integer) {
158: fs = FormatedString.format(((Integer) o)
159: .intValue(), fields[i].fieldlen);
160: }
161: // case LONG added by Michaël MICHAUD on 18 sept. 2004
162: else if (o instanceof Long) {
163: fs = FormatedString.format(((Long) o)
164: .toString(), 0, fields[i].fieldlen);
165: } else if (o instanceof java.math.BigDecimal) {
166: fs = FormatedString.format(((BigDecimal) o)
167: .toString(), 0, fields[i].fieldlen);
168: } else
169: ;
170: if (fs.length() > fields[i].fieldlen)
171: fs = FormatedString.format(0,
172: fields[i].fieldlen);
173: ls.writeBytesLE(fs);
174: break;
175: } else {
176: if (o instanceof Double) {
177: fs = FormatedString.format(((Double) o)
178: .toString(), fields[i].fieldnumdec,
179: fields[i].fieldlen);
180: } else if (o instanceof java.math.BigDecimal) {
181: fs = FormatedString.format(((BigDecimal) o)
182: .toString(), fields[i].fieldnumdec,
183: fields[i].fieldlen);
184: } else
185: ;
186: if (fs.length() > fields[i].fieldlen)
187: fs = FormatedString.format("0.0",
188: fields[i].fieldnumdec,
189: fields[i].fieldlen);
190: ls.writeBytesLE(fs);
191: break;
192: }
193: case 'F':
194: case 'f':
195: //double
196: s = ((Double) o).toString();
197: String x = FormatedString.format(s,
198: fields[i].fieldnumdec, fields[i].fieldlen);
199: ls.writeBytesLE(x);
200: break;
201: // Case 'logical' added by Michaël Michaud on 18 sept. 2004
202: case 'L':
203: //boolean
204: if (o == null || o.equals("") || o.equals(" "))
205: ls.writeBytesLE(" ");
206: else {
207: boolean b = ((Boolean) o).booleanValue();
208: ls.writeBytesLE(b ? "T" : "F");
209: }
210: break;
211: }// switch
212: }// fields
213: }
214:
215: public void close() throws IOException {
216: ls.writeByteLE(0x1a); // eof mark
217: ls.close();
218: }
219:
220: int dp = 2; // default number of decimals to write
221:
222: }
|