DBF文件格式
项目中需要读写shp文件 里面包含一个 DBF的数据库文档,整理了一下:
DBF的文件格式:
BDF文件头的详细格式:
DBF文件头中记录项的详细格式:
DBF文件中的数据类型:
举例说明:
假如文件中有10条记录,每个记录有4个字段,4个字段的长度分别为:12、14、16、18,那么文件的详细格式如下:
文件头占32+32*4+2个字节:
前32个字节是文件头中的基本信息,32*4个字节是记录项(即字段的定义信息),最后两个字节分别是16进制的0D 和20,0D代表上文表格中说明的记录项终止标识。20代表一个空格。
数据信息占(12+14+16+18)*10+1个字节:
12+14+16+18个字节代表一条记录,共10条记录。最后一个字节是数据的终止表示通常是16进制表示的1A
补充说明:
由于上述文件格式的定义,决定了字段名称不能超过11个字节(或者5个中文字符),字符类型的字段,数据最大不能超过255个字节。在从文本、Excel、大型数据库导出数据到DBF格式文件时,一定要考虑到这些长度限制。
DBF文件是个二维表,和数据库表结构一致, 文中记录项就是字段信息,头文件中一条记录中的字节长度即为所有字段长度总和
下面是结构示意图
使用ActionScript 读写的代码如下:
基本数据类:
DBFDataType.as
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 |
package net.code2048.map.file.esri.shapefile.dbf { /** * DBF 表的字段类型枚举 * @author 破晓(www.code2048.net) * */ public class DBFDataType { /** 二进制型*/ public static const BYTE_ARRAY:uint = 0x42; //"B"; /** 字符型*/ public static const CHAR:uint = 0x43; //"C"; /** 日期型*/ public static const DATE:uint = 0x44; //"D"; /** General or OLE*/ public static const GENERAL :uint = 0x47; //"G"; /** 数值型 */ public static const NUMERIC:uint = 0x4E; //"N"; /** 逻辑型*/ public static const LOGICAL :uint = 0x4C; //"L"; /** 备注*/ public static const MEMO:uint = 0x4D; //"M"; } } |
DBFHead.as
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
package net.code2048.map.file.esri.shapefile.dbf { /** * DBF文件头信息 * @author 破晓(www.code2048.net) * */ [Bindable] public class DBFHead { public var Version:uint = 0x03; public var UpdateDate:Date = new Date(); public var RecordCount:uint = 0; public var HeadLength:uint = 0; public var RecordLength:uint = 0; public var Undo:uint = 0; public var IV:Boolean = false; public var MDX:Boolean = false; public var LDID:uint = 0; public var Fields:Array = []; public var End:uint = 13; } } |
DBFHeadFiledPosition.as
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
package net.code2048.map.file.esri.shapefile.dbf { /** * DBF文件头个字段的位置 * @author 破晓(www.code2048.net) * */ public class DBFHeadFiledPosition { public static const Version:uint = 0; public static const UpdateDate:uint = 1; public static const RecordCount:uint = 4; public static const HeadLength:uint = 8; public static const RecordLength:uint = 10; public static const Undo:uint = 14; public static const IV:uint = 15; public static const MDX:uint = 28; public static const LDID:uint = 29; public static const Fields:uint = 32; } } |
FieldInfo.as
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 |
package net.code2048.map.file.esri.shapefile.dbf { /** * DBF 表的字段信息 * @author 破晓(www.code2048.net) * */ public class FieldInfo { public function FieldInfo(fieldName:String=null, dataType:int=DBFDataType.CHAR, length:int=0, precision:int=0, workID:int=0, MDX:Boolean=false) { this.fieldName = fieldName; this.dataType = dataType; this.length = length; this.precision = precision; this.workID = workID; this.MDX = MDX; } /** 字段名称,是ASCII码值。不得超过11个字符*/ public var fieldName:String; /** 字段的数据类型,是ASCII码值。(B、C、D、G、L、M和N)*/ public var dataType:int; /** 字段长度,二进制型*/ public var length:int; /** 字段的精度,二进制型*/ public var precision:int; /** 工作区ID*/ public var workID:int; /** MDX标识。如果存在一个MDX 格式的索引文件,那么这个记录项为真,否则为空。*/ public var MDX:Boolean; } } |
基础接口:
IReader.as
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 |
package net.code2048.map.file { import flash.events.IEventDispatcher; import flash.utils.ByteArray; /** * 阅读器接口 * @author 破晓(www.code2048.net) * */ public interface IReader extends IEventDispatcher { /** * 读取数据 * @param byte * @return * */ function read(byte:ByteArray):void; /** * 返回文件数据 * @return * */ function get data():*; function reset():void; } } |
IWriter.as
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 |
package net.code2048.map.file { import flash.events.IEventDispatcher; import flash.utils.ByteArray; /** * 文件写入器接口 * @author 破晓(www.code2048.net) * */ public interface IWriter extends IEventDispatcher { /** * 写入数据 * @param data * @return * */ function write(data:*):ByteArray; /** * 获取写入完毕后的二进制数据 * @return * */ function get stream():ByteArray; } } |
Reader.as
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 |
package net.code2048.map.file.esri { import net.code2048.map.file.IReader; import flash.events.Event; import flash.events.EventDispatcher; import flash.events.ProgressEvent; import flash.utils.ByteArray; /** * 文件读取完毕 */ [Event(name="complete", type="flash.events.Event")] /** * 读取进度 */ [Event(name="progress", type="flash.events.ProgressEvent")] /** * <p>文件阅读器基类</p> * <p> * 支持同步读取和异步读取:<br/> * <li>同步读取,请直接调用read方法,如果文件过大请不要使用该方式,以免发生超时异常</li> * <li>异步读取,请使用appendData方法(无需使用read方法),对文件大小无限制,读取时间比read略长(毫秒级)</li> * </p> * <p>详细介绍:</p> * <p> * 同步读取和异步读取过程中都会派发progress事件,读取完毕都会派发complete事件<br/> * 同步读取应该选择缓存数据(cache = true)<br/> * 异步读取建议不要选择缓存数据,以免增加内存使用,异步读取为流式读取,只缓存当前append的数据(cache = false 的情况下)<br/> * 调用appendData方法读取完毕后,会执行 appendRocordsReadComplete(arr)(这里需要提前设置appendRocordsReadComplete)<br/> * 如果 appendData 追加的数据过少不足一条记录长度时,则执行appendRocordsReadComplete(arr) 时 arr.length为0<br/> * 如果想保证执行appendRocordsReadComplete(arr)时,arr里一定有数据,则在执行appendData后等待派发progress事件,<br/> * 该事件派发后,执行appendRocordsReadComplete(arr)时,arr里一定有数据,也可以主动获取currentAppendData<br/> * </p> * @author 破晓(www.code2048.net) * */ public class Reader extends EventDispatcher implements IReader { /** 是否正在读取*/ protected var isReading:Boolean; /** 头信息是否读取完毕*/ protected var headReadEnd:Boolean; /** 是否缓存数据*/ protected var _cache:Boolean; /** 是否正在读取append的数据*/ protected var isAppend:Boolean = false; protected var _currentAppendData:Array = []; /** append数据读取成功后执行的功能*/ protected var _appendRocordsReadComplete:Function; protected var isComplete:Boolean; /** 文件数据*/ protected var _byte:ByteArray; /** 读取的总进度*/ protected var totalIndex:uint = 0; /** 进度事件*/ protected var progress:ProgressEvent = new ProgressEvent(ProgressEvent.PROGRESS); /** * 构造函数 * @param cache 是否缓存数据 * */ public function Reader(cache:Boolean=true) { super(); _cache = cache; } /** * 同步读取数据,执行该方法后,也可以用appendData继续追加直至触发complete事件 * @param byte * @return * */ public function read(byte:ByteArray):void { reset(); if(byte && byte.length > 0) { var result:Boolean; _byte = byte; result = readHead(); if(result) result = readBody(); } } public function reset():void { totalIndex = 0; _byte = null; _currentAppendData = []; headReadEnd = false; isReading = false; isComplete = false; } /** * 返回读取后的文件信息, cache = true时 有效,一般用于同步读取完成后获取结果 * @return * */ public function get data():* { return null; } /** * 读取头文件 * @return * */ protected function readHead():Boolean { return false; } /** * 读取主体内容 * @return * */ protected function readBody():Boolean { return false; } /** * 追加数据 (异步加载时使用) * @param byte * */ public function appendData(byte:ByteArray):void { isAppend = true; _currentAppendData = []; if(!_byte) _byte = byte; else { var pos:uint = _byte.position; _byte.position = _byte.length; _byte.writeBytes(byte, 0, byte.length); _byte.position = pos; } if(isReading) return; if(!headReadEnd) read(_byte); else readBody(); isAppend = false; if(_appendRocordsReadComplete != null) _appendRocordsReadComplete(_currentAppendData); if(isComplete) { dispatchEvent(new Event(Event.COMPLETE)); reset(); } } /** * appendData读取完成后执行的功能 * @param fun * */ public function set appendRocordsReadComplete(fun:Function):void { _appendRocordsReadComplete = fun; } /** 当前append读取成功后的数据*/ public function get currentAppendData():Array { return _currentAppendData; } } } |
Writer.as
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 |
package net.code2048.map.file.esri { import net.code2048.map.file.IWriter; import flash.events.Event; import flash.events.EventDispatcher; import flash.events.ProgressEvent; import flash.utils.ByteArray; /** * 写入完毕 */ [Event(name="complete", type="flash.events.Event")] /** * 写入进度 */ [Event(name="progress", type="flash.events.ProgressEvent")] /** * 文件写入基类 * @author 破晓(www.code2048.net) * */ public class Writer extends EventDispatcher implements IWriter { protected var _byte:ByteArray; /** 进度事件*/ protected var progress:ProgressEvent = new ProgressEvent(ProgressEvent.PROGRESS); public function Writer() { super(); } /** * 参数为数组 * @param data * @return * */ public function write(data:*):ByteArray { return _byte; } public function get stream():ByteArray { return _byte; } } } |
DBF读写类:
DBFReader.as
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 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 |
package net.code2048.map.file.esri.shapefile.dbf { import net.code2048.map.file.esri.Reader; import flash.events.Event; import flash.utils.ByteArray; import flash.utils.Dictionary; import flash.utils.Endian; /** * 读取DBF文件 * 读取后data输出类型:Array[Dictionary{field1 -> data1, field2 -> data2, field3 -> data3 ...}] * @author 破晓(www.code2048.net) * */ public class DBFReader extends Reader { private var _dbfHead:DBFHead; private var _data:Array = []; /** 文件编码*/ private var _charSet:String = "utf8"; /** * 读取DBF文件 * @param cache 是否缓存 * @param chartSet 编码类型 * */ public function DBFReader(cache:Boolean=true, chartSet:String="utf8") { _charSet = chartSet; super(cache); } override public function get data():* { return _data; } /** * 返回文件头中指定位置字段的偏移位置 * @param index 第几个字段(从1到13为有效数字,其他数字皆返回0) * @return 在文件中的字节位置 * */ public static function getHeadFiledPositionAt(index:uint):uint { var FiledsPositions:Array = [0, 1, 4, 8, 10, 12, 14, 15, 16, 28, 29, 30, 32]; if(index > 0 && index < 14) return FiledsPositions[index-1]; else return 0; } /** * 返回文件头中指定位置字段的字节数 * @param index 第几个字段(从1到12为有效数字,其他数字皆返回0) * @return 字段的字节数 * */ public static function getHeadFiledLengthAt(index:uint):uint { var FiledsLengths:Array = [1, 3, 4, 2, 2, 2, 1, 1, 12, 1, 1, 2]; if(index > 0 && index < 13) return FiledsLengths[index-1]; else return 0; } /** * 读取第几条记录 ,此函数不会改变byte的指针位置 * @param byte * @param index 第几条记录 (从1开始) * @param chartSet 编码类型 * @return * */ public static function getDataAt(byte:ByteArray, index:uint, chartSet:String="utf8"):Dictionary { var bytePos:uint = byte.position; var head:DBFHead = readHeadData(byte); var pos:uint = head.HeadLength + (index - 1) * head.RecordLength; if(byte.bytesAvailable < pos + head.RecordLength) return null; byte.position = pos + 1; var rocord:Dictionary = new Dictionary(); for each(var fi:FieldInfo in head.Fields) { rocord[fi.fieldName] = byte.readMultiByte(fi.length, chartSet).replace(/(^\s*)|(\s*$)/g, ""); // 读取数据并去掉首尾空格 } byte.position = bytePos; return rocord; } /** * 读取文件头 * @param byte * @return * */ public static function readHeadData(byte:ByteArray):DBFHead { byte.position = 0; if(byte.bytesAvailable < 33) return null; var dbfHead:DBFHead = new DBFHead(); byte.endian = Endian.LITTLE_ENDIAN; dbfHead.Version = byte.readUnsignedByte(); // 当前版本信息 一般是 0x03 var year:int = byte.readUnsignedByte(); // 年份 if(year > 90) year += 1900; else year += 2000; // 年份转换 dbfHead.UpdateDate = new Date(year, byte.readUnsignedByte() - 1, byte.readUnsignedByte()); // 读取更新日期 dbfHead.RecordCount = byte.readUnsignedInt(); // 文件中的记录条数 dbfHead.HeadLength = byte.readUnsignedShort(); // 文件头中的字节数 // 如果数据不够,则中止读取 if(byte.bytesAvailable < dbfHead.HeadLength - 10) { byte.position = 0; return null; } dbfHead.RecordLength = byte.readUnsignedShort(); // 一条记录中的字节长度 byte.position += 2; // 保留字节,用于以后添加新的说明性信息时使用,这里用0来填写 dbfHead.Undo = byte.readUnsignedByte(); // 表示未完成的操作 dbfHead.IV = byte.readBoolean(); // dBASE IV编密码标记。 byte.position += 12; // 保留字节,用于多用户处理时使用。(12个字节) dbfHead.MDX = byte.readBoolean(); // DBF文件的MDX标识。在创建一个DBF 表时 ,如果使用了MDX 格式的索引文件,那么 DBF 表的表头中的这个字节就自动被设置了一个标志,当你下次试图重新打开这个DBF表的时候,数据引擎会自动识别这个标志,如果此标志为真,则数据引擎将试图打开相应的MDX 文件。 dbfHead.LDID = byte.readUnsignedByte(); //Language driver ID byte.position += 2; // 保留字节,用于以后添加新的说明性信息时使用,这里用0来填写 var endPos:uint = dbfHead.HeadLength - 1; var ri:FieldInfo; while(byte.position < endPos) { ri = new FieldInfo(); ri.fieldName = byte.readMultiByte(11, "ASCII"); // 记录项名称,是ASCII码值 ri.dataType = byte.readUnsignedByte(); // 记录项的数据类型,是ASCII码值。(B、C、D、G、L、M和N) byte.position += 4; // 保留字节,用于以后添加新的说明性信息时使用,这里用0来填写 ri.length = byte.readUnsignedByte(); // 记录项长度,二进制型 ri.precision = byte.readUnsignedByte(); // 记录项精度,二进制型 byte.position += 2; // 保留字节,用于以后添加新的说明性信息时使用,这里用0来填写 ri.workID = byte.readUnsignedByte(); byte.position += 10; // 保留字节,用于以后添加新的说明性信息时使用,这里用0来填写 ri.MDX = byte.readBoolean(); // MDX标识。如果存在一个MDX 格式的索引文件,那么这个记录项为真,否则为空 dbfHead.Fields.push(ri); } dbfHead.End = byte.readUnsignedByte(); //结束符 (作为记录项终止标识) 一般为 0x0D (char 13) return dbfHead; } override protected function readHead():Boolean { _data = []; isReading = true; _dbfHead = readHeadData(_byte); isReading = false; if(!_dbfHead) return false; headReadEnd = true; // 派发进度 totalIndex = 1; progress.bytesLoaded = totalIndex; progress.bytesTotal = _dbfHead.RecordCount + 1; dispatchEvent(progress); return true; } override protected function readBody():Boolean { isReading = true; var rocord:Dictionary; var tempByte:ByteArray; while(totalIndex <= _dbfHead.RecordCount) { if(_byte.bytesAvailable < _dbfHead.RecordLength) { if(!_cache) { tempByte = new ByteArray(); _byte.readBytes(tempByte, 0, _byte.bytesAvailable); _byte = tempByte; _byte.position = 0; } break; } _byte.position += 1; // 忽略空格 rocord = new Dictionary(); for each(var fi:FieldInfo in _dbfHead.Fields) { rocord[fi.fieldName] = _byte.readMultiByte(fi.length, _charSet).replace(/(^\s*)|(\s*$)/g, ""); // 读取数据并去掉首尾空格 } if(isAppend) _currentAppendData.push(rocord); if(_cache) _data.push(rocord); // 派发进度 totalIndex++ progress.bytesLoaded = totalIndex; dispatchEvent(progress); } isReading = false; // 派发读取完成事件 if(totalIndex == _dbfHead.RecordCount + 1) { isComplete = true; if(!isAppend) { dispatchEvent(new Event(Event.COMPLETE)); reset(); } } return true; } /** * 读取数据 此方法暂不使用 * @param byte * @param type * @return * */ private function readObject(byte:ByteArray, type:int):* { var result:*; switch(type) { case DBFDataType.BYTE_ARRAY: result = byte;break; case DBFDataType.CHAR: result = byte.readMultiByte(byte.length, "ASCII");break; case DBFDataType.DATE: { result = new Date(int(byte.readMultiByte(4, "ASCII")), int(byte.readMultiByte(2, "ASCII")), int(byte.readMultiByte(2, "ASCII"))); break; } case DBFDataType.GENERAL: { break; } case DBFDataType.LOGICAL: { break; } case DBFDataType.MEMO: { break; } case DBFDataType.NUMERIC: { break; } } return result; } /** 文件编码*/ public function get charSet():String { return _charSet; } /** * @private */ public function set charSet(value:String):void { _charSet = value; } public function get dbfHead():DBFHead { return _dbfHead; } } } |
DBFWriter.as
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 |
package net.code2048.map.file.esri.shapefile.dbf { import net.code2048.map.file.esri.Writer; import flash.utils.ByteArray; import flash.utils.Dictionary; import flash.utils.Endian; /** * 写入DBF * @author 破晓(www.code2048.net) * */ public class DBFWriter extends Writer { private var dbfHead:DBFHead; // 文件头 private var _chartSet:String; private var _Fields:Array; public function DBFWriter(chartSet:String="utf8") { _chartSet = chartSet; super(); } public static function appendData(data:Array, head:DBFHead, charSet:String="utf8"):Dictionary { var result:Dictionary = new Dictionary(); head.RecordCount += data.length; head.UpdateDate = new Date(); var headByte:ByteArray = new ByteArray(); writeHead(headByte, head); result["head"] = headByte; var body:ByteArray = new ByteArray(); for each(var item:* in data) { writeItem(body, item, head.Fields, charSet); } result["body"] = body; return result; } /** * 写入DBF数据 * @param data 要求数据格式:Array[Object{field1 -> data1, field2 -> data2, field3 -> data3 ...}] * @return * */ override public function write(data:*):ByteArray { if(!_Fields || _Fields.length == 0) throw new Error("没有设置字段数据"); dbfHead = new DBFHead(); dbfHead.RecordCount = data.length; dbfHead.Fields = _Fields; dbfHead.RecordLength = 1; for each(var fieldItem:FieldInfo in _Fields) { dbfHead.RecordLength += fieldItem.length; } _byte = new ByteArray(); // 写入SHP文件头 writeHead(_byte, dbfHead); // 派发进度 progress.bytesTotal = data.length + 1; progress.bytesLoaded = 1; dispatchEvent(progress); for each(var item:* in data) { writeItem(_byte, item, _Fields, _chartSet); progress.bytesLoaded += 1; dispatchEvent(progress); } return _byte; } public static function writeItem(byte:ByteArray, item:*, fields:Array, charSet:String="utf8"):void { var dataValue:String; var startPos:uint; var endPos:uint; byte.writeByte(32); // 写入一个空格 for each(var field:FieldInfo in fields) { dataValue = item[field.fieldName]; startPos = byte.position; endPos = startPos + field.length; byte.writeMultiByte(dataValue, charSet); while(byte.position < endPos) { byte.writeByte(32); // 不足的用空格补齐 0x20 } byte.position = endPos; // 过长的截去 } } /** * 写入文件头 * @param byte * @param head */ public static function writeHead(byte:ByteArray, head:DBFHead):void { byte.position = 0; byte.endian = Endian.LITTLE_ENDIAN; byte.writeByte(head.Version); // 当前版本信息 一般是 0x03 byte.writeByte(head.UpdateDate.fullYear % 100); // 年份 byte.writeByte(head.UpdateDate.month + 1); // 月份 byte.writeByte(head.UpdateDate.date); // 日 byte.writeUnsignedInt(head.RecordCount); // 文件中的记录条数 byte.writeShort(head.HeadLength); // 文件头中的字节数 byte.writeShort(head.RecordLength); // 一条记录中的字节长度 byte.writeShort(0); // 保留字节,用于以后添加新的说明性信息时使用,这里用0来填写 byte.writeByte(head.Undo); // 表示未完成的操作 byte.writeBoolean(head.IV); // dBASE IV编密码标记。 byte.writeUnsignedInt(0); // 保留字节,用于多用户处理时使用。(12个字节) byte.writeUnsignedInt(0); byte.writeUnsignedInt(0); byte.writeBoolean(head.MDX); // DBF文件的MDX标识。在创建一个DBF 表时 ,如果使用了MDX 格式的索引文件,那么 DBF 表的表头中的这个字节就自动被设置了一个标志,当你下次试图重新打开这个DBF表的时候,数据引擎会自动识别这个标志,如果此标志为真,则数据引擎将试图打开相应的MDX 文件。 byte.writeByte(head.LDID); //Language driver ID byte.writeShort(0); // 保留字节,用于以后添加新的说明性信息时使用,这里用0来填写 var startPos:uint; for each(var fieldItem:FieldInfo in head.Fields) { startPos = byte.position; byte.writeMultiByte(fieldItem.fieldName, "ASCII"); // 记录项名称,是ASCII码值 byte.position = startPos + 11; byte.writeByte(fieldItem.dataType); // 记录项的数据类型,是ASCII码值。(B、C、D、G、L、M和N) byte.writeUnsignedInt(0); // 保留字节,用于以后添加新的说明性信息时使用,这里用0来填写 byte.writeByte(fieldItem.length); // 记录项长度,二进制型 byte.writeByte(fieldItem.precision); // 记录项精度,二进制型 byte.writeShort(0); // 保留字节,用于以后添加新的说明性信息时使用,这里用0来填写 byte.writeByte(fieldItem.workID); byte.writeDouble(0);// 保留字节,用于以后添加新的说明性信息时使用,这里用0来填写 10个字节 byte.writeShort(0); byte.writeBoolean(fieldItem.MDX); // MDX标识。如果存在一个MDX 格式的索引文件,那么这个记录项为真,否则为空 } byte.writeByte(head.End); //结束符 (作为记录项终止标识) 一般为 0x0D (char 13) head.HeadLength = byte.position; byte.position = 8; byte.writeShort(head.HeadLength); // 文件头中的字节数 byte.position = head.HeadLength; } public function get chartSet():String { return _chartSet; } public function set chartSet(value:String):void { _chartSet = value; } [Inspectable(arrayType="com.azri.map.file.esri.shapefile.dbf.FieldInfo")] /** * 字段数据 * @return * */ public function get Fields():Array { return _Fields; } public function set Fields(value:Array):void { _Fields = value; } } } |