需求:
在导出操作中,导出指定的字段生成Shape文件。
问题来源:
在ArcGIS的其他数据库中,如ArcSDE、fileGDB或者MDB中存在一个字段类型BLOB—大二进制类型,它可以用来存储很多东西,如视频、图片等;但是很不幸的是Shape文件中并不支持这个字段类型,所以我们在直接导出的时候就会出现异常!
BLOB:
大二进制类型主要的操作是通过IMemoryBlobStream 接口操作的;包括将BLOB类型字段数据读取到文件中与将文件数据写入的BLOB字段中。
分析与解决:
public IEnumInvalidObject ConvertFeatureClass (
IDatasetName inputFClassName,
IQueryFilter InputQueryFilter,
ISelectionSet InputSelectionSet,
IFeatureDatasetName outputFDatasetName,
IFeatureClassName outputFClassName,
IGeometryDef OutputGeometryDef,
IFields OutputFields,
string configKey,
int FlushInterval,
int parentHWND);
这就是转换方法的参数,由于OutputFields是来源于我们需要转换的要素类,所以他包含了所有的要素类字段,包括BLOB。
其实这里ESRI的设计误导了我,既然我想改变输出的字段总数,当然是从这个输出字段集入手了;但是经过几个小时的尝试之后,我发现无论如何设置或者QI这个参数都是无用的,它始终与输入的要素类总数一致!
难道真的不行?不甘心的我打开ArcMap,右键这个BLOB图层,导出Shape,竟然成功了,还不包括BLOB字段;既然ArcMap可以实现,文档中也重点提出不可以,所以8成是可以实现的;
于是我将目光顶上了其他的参数,仔细查看了文档,找到了这句话:To create a featureclass with a subset of the columns from the source data use IQueryFilter::SubFields. 这次感觉找到了正确的方向~,经过了尝试果然是可行的!
总结:
1.文档还是需要仔细研究的;
2.不要被参数的命名所迷惑;
3.一个接口的参数都是很有用的!
ArcGIS Object Help代码:
Write Blob Field Contents To File Snippet
/// <summary>
/// Read the contents of a specified record (ObjectID) fom a Table for a Blob field and write to a file on disk.
/// </summary>
/// <param name="string_Filename">A System.String that is the name of a binary file to write to. Example: "C:\temp\myPicture2.bmp"</param>
/// <param name="table">An ITable interface that is the table is to have a specific row read for a BLOB.</param>
/// <param name="int32_BlobFieldIndex">A System.Int32 that is the index number of the Blob field in the Fields collection of the Table. Example: 3</param>
/// <param name="int32_ObjectID">A System.Int32 that is the specific ObjectID record for which we want to obtain the Blob field. Example: 1968</param>
/// <returns>True = successful. False = unscucceeful.</returns>
/// <remarks></remarks>
public System.Boolean WriteBlobFieldContentsToFile(System.String string_Filename, ESRI.ArcGIS.Geodatabase.ITable table, System.Int32 int32_BlobFieldIndex, System.Int32 int32_ObjectID)
{
try
{
//Get the specific Row based upon the ObjectID
ESRI.ArcGIS.Geodatabase.IRow row = table.GetRow(int32_ObjectID);
//Get the field containing the Blob field.
ESRI.ArcGIS.Geodatabase.IFields fields = row.Fields;
ESRI.ArcGIS.Geodatabase.IField field = fields.get_Field(int32_BlobFieldIndex);
//Test to ensure the index number specified is a Blob Field
if (field.Type == ESRI.ArcGIS.Geodatabase.esriFieldType.esriFieldTypeBlob)
{
//Get the Blob Field valie and save to a file on disk
ESRI.ArcGIS.esriSystem.IMemoryBlobStream memoryBlobStream = (ESRI.ArcGIS.esriSystem.IMemoryBlobStream)row.get_Value(int32_BlobFieldIndex);
memoryBlobStream.SaveToFile(string_Filename);
//success
return true;
}
else
{
//unsuccessful
return false;
}
}
catch (System.Exception ex)
{
//unsuccessful with error, interrogate more
return false;
}
}
Write Blob File Contents To Table Row Field Snippet
/// <summary>
/// Read the contents of a binary file and write to a Blob field in a new row of a table.
/// </summary>
/// <param name="string_Filename">A System.String that is the name of a binary file to read. Example: "C:\temp\myPicture.bmp"</param>
/// <param name="table">An ITable interface that is the table is to have a new row added and have a specified BLOB field populated.</param>
/// <param name="int32_BlobFieldIndex">A System.Int32 that is the index number of the Blob field in the Fields collection of the Table. Example: 3</param>
/// <returns>True = successful. False = unscucceeful.</returns>
/// <remarks></remarks>
public System.Boolean WriteBlobFileContentsToTableRowField(System.String string_Filename, ESRI.ArcGIS.Geodatabase.ITable table, System.Int32 int32_BlobFieldIndex)
{
try
{
//Read the Blob (binary) stream from a file.
ESRI.ArcGIS.esriSystem.IMemoryBlobStream memoryBlobStream = new ESRI.ArcGIS.esriSystem.MemoryBlobStreamClass();
memoryBlobStream.LoadFromFile(string_Filename);
//Add a new row to the table
ESRI.ArcGIS.Geodatabase.IRow row = table.CreateRow();
//Get the Blob Field from the Table.
ESRI.ArcGIS.Geodatabase.IFields fields = row.Fields;
ESRI.ArcGIS.Geodatabase.IField field = fields.get_Field(int32_BlobFieldIndex);
//Test to ensure the index number specified is a Blob Field
if (field.Type == ESRI.ArcGIS.Geodatabase.esriFieldType.esriFieldTypeBlob)
{
//Write the Blob (binary) stream to the Blob Field and save
row.set_Value(int32_BlobFieldIndex, (System.Object)memoryBlobStream);
//row.get_Value(int32_BlobFieldIndex) = memoryBlobStream;
row.Store();
//success
return true;
}
else
{
//unsuccessful
return false;
}
}
catch (System.Exception ex)
{
//unsuccessful with error, interrogate more
return false;
}
}