使用 ODBC 从 Java 读取 Visual Foxpro 数据
Posted
技术标签:
【中文标题】使用 ODBC 从 Java 读取 Visual Foxpro 数据【英文标题】:Reading Visual Foxpro Data From Java using ODBC 【发布时间】:2013-05-05 01:30:21 【问题描述】:我正在尝试从我的 Java 应用程序中查询一个 dbf 表。我参考了这个thread
我使用 ODBC 数据源管理器创建了一个系统数据源,我将数据源名称设置为 VFPDS,并将数据库类型设置为 .DBC,最后我将路径设置为 .dbc 文件。
以下是我的java代码:
import javax.swing.* ;
import java.awt.* ;
import java.awt.event.* ;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.Statement;
// Import custom library containing myRadioListener
import java.sql.DriverManager;
public class testodbc
public static void main( String args[] )
try
// Load the database driver
Class.forName( "sun.jdbc.odbc.JdbcOdbcDriver" ) ;
// Get a connection to the database
Connection conn = DriverManager.getConnection( "jdbc:odbc:VFPDS" ) ;
// Print all warnings
for( SQLWarning warn = conn.getWarnings(); warn != null; warn = warn.getNextWarning() )
System.out.println( "SQL Warning:" ) ;
System.out.println( "State : " + warn.getSQLState() ) ;
System.out.println( "Message: " + warn.getMessage() ) ;
System.out.println( "Error : " + warn.getErrorCode() ) ;
// Get a statement from the connection
Statement stmt = conn.createStatement() ;
// Execute the query
ResultSet rs = stmt.executeQuery( "SELECT * FROM pmsquoteh" ) ;//code crashes here
// Loop through the result set
while( rs.next() )
System.out.println( rs.getString(1) ) ;
// Close the result set, statement and the connection
rs.close() ;
stmt.close() ;
conn.close() ;
catch( SQLException se )
se.printStackTrace();
System.out.println( "SQL Exception:" ) ;
// Loop through the SQL Exceptions
while( se != null )
se.printStackTrace();
System.out.println( "State : " + se.getSQLState() ) ;
System.out.println( "Message: " + se.getMessage() ) ;
System.out.println( "Error : " + se.getErrorCode() ) ;
se = se.getNextException() ;
catch( Exception e )
System.out.println( e ) ;
我遇到了这个异常:
java.sql.SQLException: [Microsoft][ODBC Visual FoxPro Driver]Not a table.
at sun.jdbc.odbc.JdbcOdbc.createSQLException(Unknown Source)
at sun.jdbc.odbc.JdbcOdbc.standardError(Unknown Source)
at sun.jdbc.odbc.JdbcOdbc.SQLExecDirect(Unknown Source)
at sun.jdbc.odbc.JdbcOdbcStatement.execute(Unknown Source)
at sun.jdbc.odbc.JdbcOdbcStatement.executeQuery(Unknown Source)
at UsingButtons.main(testodbc.java:38)
SQL Exception:
State : S0002
Message: [Microsoft][ODBC Visual FoxPro Driver]Not a table.
Error : 123
我确定数据库中存在表 pmsquoteh,并且我的机器是 64 位机器。 我究竟做错了什么 ?我将不胜感激具体的答案。
【问题讨论】:
VFP 错误“不是表格”可能意味着很多不同的事情。这可能意味着表已损坏。这也可能意味着该表已被加密。您有可用的 VFP 副本吗?如果是这样,你能打开那里的桌子吗?如果是这样,您就知道问题出在您的连接代码上。如果不是,那就是桌子。 @TamarE.Granor,我可以打开表格并查看其中的记录。所以它不是桌子 【参考方案1】:我能够在 Windows 7 上使用 jdbc-odbc 桥访问 FoxPro 表,但需要执行一些步骤。我已经安装了 VFP 驱动程序,但我不记得我是从哪里下载的,所以我没有那个链接。
我在这里复制了 jbdc:odbc 示例中的代码:http://www.java2s.com/Code/Java/Database-SQL-JDBC/SimpleexampleofJDBCODBCfunctionality.htm。
DriverManager.getConnection 方法采用数据库 URL。要创建 URL,您需要使用 ODBC 管理器。对我来说不幸的是,我可以通过控制面板访问的 ODBC 管理器仅适用于 64 位数据源。我不知道 64 位 foxpro 驱动程序。
要生成 32 位 DSN,您需要运行 32 位 ODBC 管理器:odbcad32.exe。我的机器有几个副本。我从 C:\Windows\SysWOW64 运行了一个。转到系统 DSN 选项卡并选择 Microsoft Visual Foxpro 驱动程序。当您单击完成时,您将看到一个对话框,询问数据源名称、描述和 FoxPro 数据库或表的路径。您还必须指定是要连接到 .dbc 还是空闲表目录。您的错误消息让我怀疑您是否在 DSN 上选择了错误的选项。
我传递给 getConnection 方法的数据库 URL 是“jdbc:odbc:mydsnname”。
运行后,我收到一个错误:
[Microsoft][ODBC Driver Manager] 指定的 DSN 包含一个 驱动程序和应用程序之间的架构不匹配
这是因为我使用的是 64 位 JVM 和 32 位 DSN。我下载了一个 32 位 JVM,并且能够使用它来运行我的示例类。
我不知道你是否可以在 64 位 JVM 上设置一个开关来告诉它以 32 位运行。
【讨论】:
【参考方案2】:我从这里使用了 JDBC 驱动程序:
http://www.csv-jdbc.com/relational-junction/jdbc-database-drivers-products/new-relational-junction-dbf-jdbc-driver/
对我来说很好用。到目前为止(大约一个小时)的测试中,它读取 MEMO 文件,并且似乎对包含 DBC 的表或空闲 DBF 没有任何问题。
不确定这个驱动程序的成本是多少。由于 VFP 已经过时,客户可能最多只支付 100 美元。
【讨论】:
【参考方案3】:过去六个月我使用 javadbf-0.4.0.jar 没有问题。我将发布我的 Java 类和主程序。
package foxtablereader.src;
import java.sql.Connection;
import java.sql.SQLException;
import sun.jdbc.rowset.CachedRowSet;
/**
*
* @author kalimk
*/
public class DbfMain
static CachedRowSet crs;
/**
* @param args the command line arguments
*/
public static void main(String[] args) throws SQLException
DbfConnection foxconn = new DbfConnection();
Connection connection = null;
String inputTablePath = "c:\\vfp_table\\";
connection = foxconn.connection(inputTablePath);
String query = "SELECT * FROM TrigExport2.dbf ";
crs = foxconn.select(query, connection);
//crs = ft.query(query, inputTablePath);
System.out.println(" Size " + crs.size());
while (crs.next())
System.out.println("DESC " + crs.getString("Serialnum") + " " + crs.getString("cmailcode"));
inputTablePath = "C:\\sourcecode\\FoxTableReader\\";
connection = foxconn.connection(inputTablePath);
query = "SELECT * FROM TrigExports.dbf ";
crs = foxconn.select(query, connection);
System.out.println(" Size " + crs.size());
int z = 1;
while (crs.next())
System.out.println(z++ + " " + crs.getString("Serialnum") + " " + crs.getString("cmailcode"));
inputTablePath = "C:\\sourcecode\\FoxTableReader\\";
connection = foxconn.connection(inputTablePath);
String queryinsert = "insert into Mcdesc (Desc,Mailcode,Del_type,Column1) values ('Kalim','KHAN', 'ERUM','KHAN')";
foxconn.insertUpdate(queryinsert, connection);
inputTablePath = "C:\\sourcecode\\FoxTableReader\\";
connection = foxconn.connection(inputTablePath);
String queryupdate = "update Mcdesc set Column1= 'Sadiqquie' where Desc = 'Kalim'";
foxconn.insertUpdate(queryupdate, connection);
package foxtablereader.src;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import sun.jdbc.rowset.CachedRowSet;
/**
*
* @author kalimk
*/
public class DbfConnection
public Connection connection(String inputTablePath) throws SQLException
Connection con = null;
//String jdbURL = "jdbc:DBF:/C:\\vfp_table\\";
String jdbURL = "jdbc:DBF:/" + inputTablePath;
Properties props = new Properties();
props.setProperty("delayedClose", "0");
try
Class.forName("com.caigen.sql.dbf.DBFDriver");
try
con = DriverManager.getConnection(jdbURL, props);
catch (SQLException ex)
Logger.getLogger(DbfConnection.class.getName()).log(Level.SEVERE, null, ex);
catch (ClassNotFoundException ex)
Logger.getLogger(DbfConnection.class.getName()).log(Level.SEVERE, null, ex);
return con;
public CachedRowSet select(String cQuery, Connection con)
CachedRowSet crs = null;
try
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery(cQuery);
crs = new CachedRowSet();
crs.populate(rs);
stmt.close();
catch (Exception e)
System.out.println(e.getMessage());
e.printStackTrace();
return crs;
public boolean insertUpdate(String cQuery, Connection con)
boolean crs = false;
try
PreparedStatement pStmnt = con.prepareStatement(cQuery);
crs = pStmnt.execute();
pStmnt.close();
catch (Exception e)
System.out.println(e.getMessage());
e.printStackTrace();
return crs;
public int insertUpdateCount(String cQuery, Connection con)
int count = 0;
try
Statement stmt = con.createStatement();
count = stmt.executeUpdate(cQuery);
System.out.println("Number of rows updated in database = " + count);
stmt.close();
catch (Exception e)
System.out.println(e.getMessage());
e.printStackTrace();
return count;
public int insertUpdateCount2(String cQuery, Connection con)
int count = 0;
boolean crs = false;
try
PreparedStatement pStmnt = con.prepareStatement(cQuery);
count = pStmnt.executeUpdate(cQuery);
pStmnt.close();
catch (Exception e)
System.out.println(e.getMessage());
e.printStackTrace();
return count;
public static void DBDisconnect(Connection DBCon)
try
if (DBCon != null)
DBCon.close();
catch (SQLException e)
System.out.println(e.toString());
finally
try
DBCon.close();
//System.err.println("Fimally is always executed");
catch (SQLException ex)
Logger.getLogger(DbfConnection.class.getName()).log(Level.SEVERE, null, ex);
【讨论】:
没有关于您从何处获得此驱动程序的信息?以上是关于使用 ODBC 从 Java 读取 Visual Foxpro 数据的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Visual Studio 2019 和 .NET Core 3.0 中使用 ODBC 连接?
使用 UCanAccess 代替 JDBC-ODBC Bridge 来读取 excel 表