-
Notifications
You must be signed in to change notification settings - Fork 0
/
classDBFWriter.cs
213 lines (196 loc) · 8 KB
/
classDBFWriter.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
using System;
using System.IO;
using System.Windows.Forms;
namespace SBuilderXX
{
public class DBFWriter
{
private short nFields = 0;
private bool fileIsOpened = false;
private bool headerDone = false;
private short nBytesInRecord;
private int NoOfRecords = 0;
private short NoOfBytesInHeader;
private FileStream fs;
private BinaryWriter bw;
private const byte shp_CHARACTER = 67; // C
private const byte shp_NUMERIC = 78; // N
private const byte shp_FLOAT = 70; // F
public struct Field
{
public string Name;
public byte Type;
public byte Lenght;
public byte DecCount;
}
private Field[] Fields = new Field[129];
private int[] FieldStart = new int[129]; // points to the start of the field in a record
public bool FileWriter(string filename, int nRecords)
{
bool FileWriterRet = default;
try
{
FileWriterRet = false;
headerDone = false;
fileIsOpened = false;
nBytesInRecord = 0;
NoOfRecords = 0;
string DBFile = Path.ChangeExtension(filename, ".DBF");
if (File.Exists(DBFile))
File.Delete(DBFile);
fs = new FileStream(DBFile, FileMode.Create);
bw = new BinaryWriter(fs);
DateTime today = DateTime.Now;
bw.Write((byte)3);
bw.Write((byte)(today.Year - 1900));
bw.Write((byte)today.Month);
bw.Write((byte)today.Day);
bw.Write(nRecords); // byte 4 - 7
// accounts for the leading space on each record note that
// FieldStart(2) = FieldStart(1) + Fields(1).Lenght and so on ...
FieldStart[1] = 1;
NoOfRecords = nRecords;
FileWriterRet = true;
fileIsOpened = true;
return FileWriterRet;
}
catch (Exception)
{
MessageBox.Show("Could not create database file!", "Exception", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
fileIsOpened = false;
bw.Close();
fs.Close();
return FileWriterRet;
}
}
public bool CreateField(string name, byte type, byte len, byte dec)
{
bool CreateFieldRet = false;
int N;
try
{
if (!fileIsOpened)
return CreateFieldRet;
if (headerDone)
return CreateFieldRet;
if (type != shp_CHARACTER)
{
if (type != shp_FLOAT)
{
if (type != shp_NUMERIC)
return CreateFieldRet;
}
}
// validate arguments
if (type == shp_CHARACTER)
dec = 0;
if (len == 0)
return CreateFieldRet;
if (len - dec < 1)
return CreateFieldRet;
// now start the writing
int ptr = (nFields + 1) * 32;
name = name.Trim(); // remove any trailing or leading spaces
N = name.Length;
if (N > 11)
{
name = name.Substring(0, 11);
N = 11;
}
bw.Seek(ptr, SeekOrigin.Begin);
byte[] b; // binary.writer(string) also rights the len of string :-(
b = System.Text.Encoding.UTF8.GetBytes(name); // so transform string into array of bytes
bw.Write(b);
bw.Seek(11 - N, SeekOrigin.Current);
bw.Write(type); // byte 11
bw.Seek(4, SeekOrigin.Current);
bw.Write(len); // byte 16
bw.Write(dec); // byte 17
nFields = (short)(nFields + 1); // array Fields(0) and StartField(0) is ignored!
Fields[nFields].Name = name;
Fields[nFields].Type = type;
Fields[nFields].Lenght = len;
Fields[nFields].DecCount = dec;
FieldStart[nFields + 1] = FieldStart[nFields] + len;
nBytesInRecord = (short)(nBytesInRecord + len);
CreateFieldRet = true;
}
catch (Exception)
{
MessageBox.Show("Could not create database field: " + name + "!", "Exception", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
CreateFieldRet = false;
}
return CreateFieldRet;
}
public bool AppendFields()
{
bool AppendFieldsRet = default;
AppendFieldsRet = false;
headerDone = false;
if (nFields == 0)
return AppendFieldsRet;
nBytesInRecord = (short)(nBytesInRecord + 1); // there is a leading space on each record!
try
{
// point to bytes 8-9
bw.Seek(8, SeekOrigin.Begin);
// calculate number of bytes in header
NoOfBytesInHeader = (short)(32 * (nFields + 1) + 1); // add one for the terminator 13
bw.Write(NoOfBytesInHeader);
bw.Write(nBytesInRecord);
bw.Seek(NoOfBytesInHeader - 1, SeekOrigin.Begin);
bw.Write((byte)13); // add the terminator for the header
// fill the table with spaces
string mySpaces = new string(' ', NoOfRecords * nBytesInRecord);
byte[] b; // binary.writer(string) also rights the len of string :-(
b = System.Text.Encoding.UTF8.GetBytes(mySpaces); // so transform string into array of bytes
bw.Write(b);
bw.Write((byte)26); // 26 is 1A the terminator for the file
Array.Resize(ref FieldStart, nFields + 1); // it will eliminate the last field as (field + 1) will not appear
Array.Resize(ref Fields, nFields + 1);
AppendFieldsRet = true;
headerDone = true;
return AppendFieldsRet;
}
catch (Exception)
{
MessageBox.Show("Could not append database fields!", "Exception", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
AppendFieldsRet = false;
headerDone = false;
return AppendFieldsRet;
}
}
public bool AddRecord(int record, int field, string value)
{
bool AddRecordRet = default;
// when calling and for numeric or floating types
// value should be passed as a string! No conversion made here!
AddRecordRet = false;
try
{
byte[] b; // to strip the lenght at the start of the string
if (!headerDone)
return AddRecordRet;
if (field > nFields)
return AddRecordRet;
int myLen = Fields[field].Lenght;
int ptr = NoOfBytesInHeader + nBytesInRecord * (record - 1) + FieldStart[field];
bw.Seek(ptr, SeekOrigin.Begin);
value = value.Trim();
value = value.Substring(0, myLen); // just to make sure the string can go to the allocated space
b = System.Text.Encoding.UTF8.GetBytes(value); // transform string into array of bytes
bw.Write(b);
AddRecordRet = true;
}
catch (Exception)
{
}
return AddRecordRet;
}
public void Close()
{
bw.Close();
fs.Close();
}
}
}