我一直在研究一个读取dbf文件的程序,弄乱数据并将其保存回dbf。我遇到的问题特别与写作部分有关。
private const string constring = "Driver={Microsoft dBASE Driver (*.dbf)};"
+ "SourceType=DBF;"
+ "DriverID=277;"
+ "Data Source=¿;"
+ "Extended Properties=dBASE IV;";
private const string qrystring = "SELECT * FROM [¿]";
public static DataTable loadDBF(string location)
{
string filename = ConvertLongPathToShort(Path.GetFileName(location));
DataTable table = new DataTable();
using(OdbcConnection conn = new OdbcConnection(RTN(constring, filename)))
{
conn.Open();
table.Load(new OdbcCommand(RTN(qrystring, filename), conn).ExecuteReader());
conn.Close();
}
return table;
}
private static string RTN(string stmt, string tablename)
{ return stmt.Replace("¿", tablename); }
[DllImport("Kernel32", CharSet = CharSet.Auto)]
static extern Int32 GetShortPathName(
String path, // input string
StringBuilder shortPath, // output string
Int32 shortPathLength); // StringBuilder.Capacity
public static string ConvertLongPathToShort(string longPathName)
{
StringBuilder shortNameBuffer;
int size;
shortNameBuffer = new StringBuilder();
size = GetShortPathName(longPathName, shortNameBuffer, shortNameBuffer.Capacity);
if (size >= shortNameBuffer.Capacity)
{
shortNameBuffer.Capacity = size + 1;
GetShortPathName(longPathName, shortNameBuffer, shortNameBuffer.Capacity);
}
return shortNameBuffer.ToString();
}
这就是我正在使用的。我已经尝试了许多方法来编写一个新文件,但没有一个是高效的。说实话,虽然通常我会成为形式和功能的拥护者,但我只是想让该死的东西工作,这个应用程序应该做一个非常具体的事情,它不会模拟天气。
- =#编辑#= -
由于时间压力,我已经停止了应用程序,但在我废弃它之前,我意识到我正在使用的dbf的特定格式没有主要密钥信息。这当然意味着我必须基本上将数据读出到DataTable,弄乱它,然后擦除dbf中的所有记录并从头开始插入所有内容。 把它拧成云雀。
答案 0 :(得分:5)
对于未来来到这里的人们:我今天写了这篇文章并且运作良好。文件名没有扩展名(.dbf)。路径(用于连接)仅是目录路径(无文件)。您可以将数据表添加到数据集并将其传入。此外,我的一些数据类型是foxpro数据类型,可能与所有DBF文件不兼容。希望这会有所帮助。
public static void DataSetIntoDBF(string fileName, DataSet dataSet)
{
ArrayList list = new ArrayList();
if (File.Exists(Path + fileName + ".dbf"))
{
File.Delete(Path + fileName + ".dbf");
}
string createSql = "create table " + fileName + " (";
foreach (DataColumn dc in dataSet.Tables[0].Columns)
{
string fieldName = dc.ColumnName;
string type = dc.DataType.ToString();
switch (type)
{
case "System.String":
type = "varchar(100)";
break;
case "System.Boolean":
type = "varchar(10)";
break;
case "System.Int32":
type = "int";
break;
case "System.Double":
type = "Double";
break;
case "System.DateTime":
type = "TimeStamp";
break;
}
createSql = createSql + "[" + fieldName + "]" + " " + type + ",";
list.Add(fieldName);
}
createSql = createSql.Substring(0, createSql.Length - 1) + ")";
OleDbConnection con = new OleDbConnection(GetConnection(Path));
OleDbCommand cmd = new OleDbCommand();
cmd.Connection = con;
con.Open();
cmd.CommandText = createSql;
cmd.ExecuteNonQuery();
foreach (DataRow row in dataSet.Tables[0].Rows)
{
string insertSql = "insert into " + fileName + " values(";
for (int i = 0; i < list.Count; i++)
{
insertSql = insertSql + "'" + ReplaceEscape(row[list[i].ToString()].ToString()) + "',";
}
insertSql = insertSql.Substring(0, insertSql.Length - 1) + ")";
cmd.CommandText = insertSql;
cmd.ExecuteNonQuery();
}
con.Close();
}
private static string GetConnection(string path)
{
return "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + path + ";Extended Properties=dBASE IV;";
}
public static string ReplaceEscape(string str)
{
str = str.Replace("'", "''");
return str;
}
答案 1 :(得分:2)
使用ADO.Net读取和写入dbf文件结果非常慢,所以我建议你使用另一种方法。
一种选择是使用旧的DAO 3.6库。这更快,同样兼容,但取决于com对象的工作。
更好的方法是使用开源DBFExporter component。它可能需要一些代码来设置(你需要一个具有描述你的记录集的属性的类,并且属性必须设置某些属性),但之后它的效果非常好。它使用起来很快,但它不会读取dbf文件。该组件是LGPL下的许可证,因此您应该能够在商业代码中使用它。
答案 2 :(得分:1)
您使用的是哪种dbf文件? (有几种,例如dBase,FoxPro等不是100%兼容的。)我已经将它与C#的Microsoft Visual FoxPro OleDB提供程序一起使用,你可以给它一个镜头而不是使用dBase ODBC驱动程序。