C#中如何用流的方式读取arcgis的dbf文件.docx
- 文档编号:5986712
- 上传时间:2023-01-02
- 格式:DOCX
- 页数:38
- 大小:24.05KB
C#中如何用流的方式读取arcgis的dbf文件.docx
《C#中如何用流的方式读取arcgis的dbf文件.docx》由会员分享,可在线阅读,更多相关《C#中如何用流的方式读取arcgis的dbf文件.docx(38页珍藏版)》请在冰豆网上搜索。
C#中如何用流的方式读取arcgis的dbf文件
新制作了一个库存管理软件(c/s),数据库用mssql,客户端用.net开发。
用户在客户端对数据进行查看、添加、导入、编辑、删除、打印等操作。
公司原来的一些数据存储在.dbf文件中,必须在客户端对.dbf文件进行访问,以导入数据。
从网上搜集到关于.dbf文件格式的信息和一部分c语言直接访问.dbf文件的实例,写了一个c#直接访问.dbf的类,支持直接获取.dbf文件的DataSet,获取单个字段信息等。
1。
定义.dbf文件头类
namespaceSunman.DBF
...{
usingSystem;
/**////
///.dbf文件的文件头信息类
///
internalclassDBFHeader
...{
publicconstintDBFHeaderSize=32;
/**//*版本标志
0x02FoxBASE
0x03FoxBASE+/dBASEIIIPLUS,无备注
0x30VisualFoxPro
0x43dBASEIVSQL表文件,无备注
0x63dBASEIVSQL系统文件,无备注
0x83FoxBASE+/dBASEIIIPLUS,有备注
0x8BdBASEIV有备注
0xCBdBASEIVSQL表文件,有备注
0xF5FoxPro2.x(或更早版本)有备注
0xFBFoxBASE
*/
publicsbyteVersion;
/**//*最后更新年*/
publicbyteLastModifyYear;
/**//*最后更新月*/
publicbyteLastModifyMonth;
/**//*最后更新日*/
publicbyteLastModifyDay;
/**//*文件包含的总记录数*/
publicuintRecordCount;
/**//*第一条记录的偏移值,这个值也可以表示文件头长度*/
publicushortHeaderLength;
/**//*记录长度,包括删除标志*/
publicushortRecordLength;
/**//*保留*/
publicbyte[]Reserved=newbyte[16];
/**//*表的标志
0x01具有.cdx结构的文件
0x02文件包含备注
0x04文件是数据库(.dbc)
标志可OR
*/
publicsbyteTableFlag;
/**//*代码页标志*/
publicsbyteCodePageFlag;
/**//*保留*/
publicbyte[]Reserved2=newbyte[2];
}
}
2。
定义.dbf文件字段信息类。
namespaceSunman.DBF
...{
usingSystem;
/**////
///.dbf文件的字段信息类
///
internalclassDBFField
...{
publicconstintDBFFieldSize=32;
/**//*字段名称*/
publicbyte[]Name=newbyte[11];
/**//*字段类型C-字符型
Y-货币型
N-数值型
F-浮点型
D-日期型
T-日期时间型
B-双精度型
I-整型
L-逻辑型
M-备注型
G-通用型
C-字符型(二进制)
M-备注型(二进制)
P-图片型
*/
publicsbyteType;
/**//*字段偏移量*/
publicuintOffset;
/**//*字段长度*/
publicbyteLength;
/**//*浮点数小数部分长度*/
publicbytePrecision;
/**//*保留*/
publicbyte[]Reserved=newbyte[2];
/**//*dBASEIVworkareaid*/
publicsbyteDbaseivID;
/**//**/
publicbyte[]Reserved2=newbyte[10];
/**//**/
publicsbyteProductionIndex;
}
}
3。
.dbf文件访问类。
使用System.IO.BinaryReader类来读取.dbf文件的二进制数据,然后根据不同的字段类型和数据在.dbf文件里的存储格式对读取到的二进制数据进行解码操作。
(1)。
Numeric、float、char型的数据都是明文存储,也只要将二进制数据转换为对应的字符串形式然后转换为相应的数据类型即可。
(2)。
Integer型:
32位。
存储的就是integer类型数据的内存格式,将各个字节的数据移位然后或上即可。
(3)。
Double型:
64位,不定精度。
应该也是double类型数据的内存格式,由于小数位数不确定,使用指针直接获取内存信息。
(4)。
Currency型:
64位,精度很重要(明确为4位)。
读取到的数据.net中用Decimal类型存储。
.dbf文件中存储的应该是Currency数据放大10000倍后的long类型数据的内存格式,所以现将文件中的二进制数据读取为对应的int64类型数据,然后缩小10000倍就行。
(5)。
Date型:
64位。
存储的也是明文,前32位为带世纪的年度,后16位为日,剩下的16位为月。
(6)。
DateTime型:
64位。
存储格式与Date型差异就大了。
我认为前32位存储的是日期相对于某一日(还没弄清楚是那一日,只是离1年1月1日有1721426天的差距),后32位存储的是时间部分的毫秒数,我就分日期部分和时间部分读取。
将日期部分读取为int32数据的天数,减去1721426后,增加到1年1月1日,得到日期部分;读取时间部分的数据为int32的毫秒数,增加到前面获取到的日期上,得到完整的日期。
获取到字段数据后,再对数据进行排错处理。
这个主要是针对.dbf中numeric型和float型数据可以只存在空格和"."的现象和boolean型数据存储的是“T”和“F”。
代码如下:
namespaceSunman.DBF
...{
usingSystem;
usingSystem.IO;
/**////
///.dbf文件操作类
///
publicclassDBFFile:
IDisposable
...{
privateconststringMSG_OPEN_FILE_FAIL="不能打开文件{0}";
privatebool_isFileOpened;
privatebyte[]_recordBuffer;
privateDBFField[]_dbfFields;
privateSystem.IO.FileStream_fileStream=null;
privateSystem.IO.BinaryReader_binaryReader=null;
privatestring_fileName=string.Empty;
privateuint_fieldCount=0;
privateint_recordIndex=-1;
privateuint_recordCount=0;
privateDBFHeader_dbfHeader=null;
/**////
///构造函数
///
publicDBFFile()
...{
}
/**////
///构造函数
///
///
publicDBFFile(stringfileName)
...{
if(null!
=fileName&&0!
=fileName.Length)
this._fileName=fileName;
}
/**////
///清理所有正在使用的资源。
///
protectedvirtualvoidDispose(booldisposing)
...{
if(disposing)
...{
this._recordBuffer=null;
this._dbfHeader=null;
this._dbfFields=null;
if(this.IsFileOpened&&null!
=this._fileStream)
...{
this._fileStream.Close();
this._binaryReader.Close();
}
this._fileStream=null;
this._binaryReader=null;
this._isFileOpened=false;
this._fieldCount=0;
this._recordCount=0;
this._recordIndex=-1;
}
}
/**////
///打开dbf文件
///
///
publicboolOpen()
...{
try
...{
returnthis.Open(null);
}
catch(Exceptione)
...{
throwe;
}
}
/**////
///打开dbf文件
///
///
///
publicboolOpen(stringfileName)
...{
if(null!
=fileName)
this._fileName=fileName;
boolret=false;
try
...{
if(!
this.OpenFile())
...{
//不能打开dbf文件,抛出不能打开文件异常
thrownewException(string.Format(MSG_OPEN_FILE_FAIL,this._fileName));
}
//读取文件头信息
ret=this.ReadFileHeader();
//读取所有字段信息
if(ret)
ret=this.ReadFields();
//分配记录缓冲区
if(ret&&null==this._recordBuffer)
...{
this._recordBuffer=newbyte[this._dbfHeader.RecordLength];
if(null==this._recordBuffer)
ret=false;
}
//如果打开文件或读取信息不成功,关闭dbf文件
if(!
ret)
this.Close();
}
catch(Exceptione)
...{
throwe;
}
//设置当前记录索引为
this._recordIndex=-1;
//返回打开文件并且读取信息的成功状态
returnret;
}
/**////
///获取dbf表文件对应的DataSet
///
///
publicSystem.Data.DataSetGetDataSet()
...{
//确保文件已经打开
if(!
this.IsFileOpened||(this.IsBOF&&this.IsEOF))
returnnull;
//构造表格
System.Data.DataSetds=newSystem.Data.DataSet();
System.Data.DataTabledt=newSystem.Data.DataTable(System.IO.Path.GetFileNameWithoutExtension(this._fileName));
try
...{
//添加表格列
for(uinti=0;i ...{ System.Data.DataColumncol=newSystem.Data.DataColumn(); stringcolText=string.Empty; //获取并设置列标题 if(this.GetFieldName(i,refcolText)) ...{ col.ColumnName=colText; col.Caption=colText; } //设置列类型 switch(this._dbfFields[i].Type) ...{ //C-字符型、字符型(二进制) case(sbyte)'C': col.DataType=typeof(System.String); break; //Y-货币型 case(sbyte)'Y': col.DataType=typeof(System.Decimal);//虽然dbf中'Y'长度为64位,但是Double的精度不够,所以指定Decimal break; //N-数值型 case(sbyte)'N': col.DataType=typeof(System.Decimal);//dbf中'N'的精度可以达到19,所以用Decimal break; //F-浮点型 case(sbyte)'F': col.DataType=typeof(System.Decimal);//dbf中'F'的精度可以达到19,所以用Decimal break; //D-日期型 case(sbyte)'D': col.DataType=typeof(System.DateTime); break; //T-日期时间型 case(sbyte)'T': col.DataType=typeof(System.DateTime); break; //B-双精度型 case(sbyte)'B': col.DataType=typeof(System.Double); break; //I-整型 case(sbyte)'I': col.DataType=typeof(System.Int32); break; //L-逻辑型 case(sbyte)'L': col.DataType=typeof(System.Boolean); break; //M-备注型、备注型(二进制) case(sbyte)'M': col.DataType=typeof(System.String); break; //G-通用型 case(sbyte)'G': col.DataType=typeof(System.String); break; //P-图片型 case(sbyte)'P': col.DataType=typeof(System.String); break; //缺省字符串型 default: col.DataType=typeof(System.String); break; } //添加列信息 dt.Columns.Add(col); } //添加所有的记录信息 this.MoveFirst(); while(! this.IsEOF) ...{ //创建新记录行 System.Data.DataRowrow=dt.NewRow(); //循环获取所有字段信息,添加到新的记录行内 for(uinti=0;i ...{ stringtemp=string.Empty; //获取字段值成功后才添加到记录行中 if(this.GetFieldValue(i,reftemp)) ...{ //如果获取的字段值为空,设置DataTable里字段值为DBNull //if(string.Empty! =temp) row[(int)i]=temp; //else //row[(int)i]=System.DBNull.Value; } } //添加记录行 dt.Rows.Add(row); //后移记录 this.MoveNext(); } } catch(Exceptione) ...{ throwe; } ds.Tables.Add(dt); returnds; } /**//// ///获取相应索引序号处的字段名称 /// /// /// /// publicboolGetFieldName(uintfieldIndex,refstringfieldName) ...{ //确保文件已经打开 if(! this.IsFileOpened) returnfalse; //索引边界检查 if(fieldIndex>=this._fieldCount) ...{ fieldName=string.Empty; returnfalse; } try ...{ //反解码 fieldName=System.Text.Encoding.Default.GetString(this._dbfFields[fieldIndex].Name); returntrue; } catch(Exceptione) ...{ throwe; } } /**//// ///获取相应索引序号处的字段文本值 /// /// /// /// publicboolGetFieldValue(uintfieldIndex,refstringfieldValue) ...{ //安全性检查 if(! this.IsFileOpened||this.IsBOF||this.IsEOF||null==this._recordBuffer) returnfalse; //字段索引超过最大值 if(fieldIndex>=this._fieldCount) ...{ fieldValue=string.Empty; returnfalse; } try ...{ //从记录缓冲区中获取对应字段的byte[] byte[]tmp=GetSubBytes(this._recordBuffer,this._dbfFields[fieldIndex].Offset, this._dbfFields[fieldIndex].Length); // //开始byte数组的反解码过程 // if(((sbyte)'I')==this._dbfFields[fieldIndex].Type) ...{ //整形字段的反解码过程 intnum1=Byte2Int32(tmp); fieldValue=num1.ToString(); } elseif(((sbyte)'B')==this._dbfFields[fieldIndex].Type) ...{ //双精度型字段的反解码过程 doublenum1=Byte2Double(tmp); fieldValue=num1.ToString(); } elseif(((sbyte)'Y')==this._dbfFields[fieldIndex].Type) ...{ // //货币型字段的反解码过程 //货币型存储的时候应该是将字段值放大10000倍,变成long型存储 //所以先将byte数组恢复成long类型数值,然后缩小10000倍。 // longnum1=Byte2Int64(tmp); fieldValue=(((decimal)num1)/10000).ToString(); } elseif(((sbyte)'D')==this._dbfFields[fieldIndex].Type) ...{ // //日期型字段的反解码过程 // DateTimedate1=Byte2Date(tmp); fieldValue=date1.ToString(); } elseif(((sbyte)'T')==this._dbfFields[fieldIndex].Type) ...{ // //日期时间型字段的反解码过程 // DateTimedate1=Byte2DateTime(tmp); fie
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- C# 何用 方式 读取 arcgis dbf 文件