【问题标题】:How do I extract the data in a FoxPro memo field using .NET?如何使用 .NET 提取 FoxPro 备忘录字段中的数据?
【发布时间】:2009-01-09 14:32:05
【问题描述】:

我正在编写一个将 FoxPro 数据库转换为 XML 的 C# 程序,除了备注字段为空之外,一切正常。有什么我缺少的东西来转换那个位吗?

我正在使用 C# .Net 3.5 SP1、Visual FoxPro 9 SP 1 OLE DB 驱动程序。连接字符串没问题,因为所有其他数据都被正确提取。

当我将 FoxPro 数据库转换为 SQL Server 时,那里的备注字段也是空白的,所以我无法转换两次。

【问题讨论】:

    标签: c# oledb visual-foxpro foxpro


    【解决方案1】:

    最终不得不自己做一些工作,但也许将来可以帮助其他人:

            public static object GetDbaseOrFoxproRawValue(string DBPath, string TableName, string ColumnName, 
            string CompareColumnName, string CompareValue, bool CompareColumnIsAutoKey)
        {
            using (BinaryReader read = new BinaryReader(File.Open(
                Path.Combine(DBPath, TableName + ".dbf"), FileMode.Open, FileAccess.Read, FileShare.ReadWrite)))
            {
                // Is it a type of file that I can handle?
                if (new byte[] { 0x02, 0x03, 0x30, 0x43, 0x63, 0x83, 0x8b,
                                 0xcb, 0xf5, 0xfb }.Contains(read.ReadByte()))
                {
                    // Skip date.
                    read.BaseStream.Seek(3, SeekOrigin.Current);
    
                    // Read useful datas...
                    uint RecordCount = read.ReadUInt32();
                    ushort FirstRecord = read.ReadUInt16();
                    ushort RecordLength = read.ReadUInt16();
                    int FieldCount = FirstRecord - 296 / 32;
    
                    // Make sure things aren't stupid.
                    ColumnName = ColumnName.ToLower();
                    CompareColumnName = CompareColumnName.ToLower();
    
                    // Find target column (field)
                    string temp;
                    UInt32 CompareFieldOffset = uint.MaxValue, FieldOffset = uint.MaxValue;
                    byte CompareFieldLength = 0, FieldLength = 0;
                    char FieldType = ' ';
                    for (int i = 0; i < FieldCount; i++)
                    {
                        read.BaseStream.Seek(32 + (i * 32), SeekOrigin.Begin);
                        temp = Encoding.ASCII.GetString(read.ReadBytes(11)).Replace("\0", "").ToLower();
                        if (temp == CompareColumnName)
                        {
                            read.ReadChar();
                            CompareFieldOffset = read.ReadUInt32();
                            CompareFieldLength = read.ReadByte();
                        }
                        if (temp == ColumnName)
                        {
                            FieldType = read.ReadChar();
                            FieldOffset = read.ReadUInt32();
                            FieldLength = read.ReadByte();
                        }
    
                        if (CompareFieldOffset != uint.MaxValue && FieldOffset != uint.MaxValue)
                            break;
                    }
    
                    // Make sure we can continue.
                    if (CompareFieldOffset == uint.MaxValue || 
                        FieldOffset == uint.MaxValue) return null;
    
                    // Iterate through each record to find the one we want.
                    for (int index = 0; index < RecordCount; index++)
                    {
                        read.BaseStream.Seek(FirstRecord + (index * RecordLength) + CompareFieldOffset, SeekOrigin.Begin);
                        temp = Encoding.Default.GetString(read.ReadBytes(CompareFieldLength)).Replace("\0", "");
                        if (temp == CompareValue)
                        {
                            read.BaseStream.Seek(FirstRecord + (index * RecordLength) + FieldOffset, SeekOrigin.Begin);
                            switch (FieldType)
                            {
                                case 'M':
                                case 'I': return read.ReadUInt32();
                                case 'C':
                                default: return Encoding.Default.GetString(read.ReadBytes(FieldLength)).Replace("\0", "");
                            }
                        }
                    }
                }
                else
                {
                    return null;
                }
            }
    
            return null;
        }
    

    只需从中获取结果并将其用作备忘录文件的索引(该代码使用 MSDN 文档非常简单)。

    【讨论】:

    • 当我复制并粘贴这段代码时,我收到一个错误“无法访问 IList.Contains 的显式实现”。在Contains 之前添加.ToList() 可以解决问题。
    • 关于在文档中从哪里开始使用此索引从备注字段获取数据的任何建议?
    • @reggaeguitar 我的摇滚明星朋友,你是真正的救星!谢谢
    【解决方案2】:

    我对 C#、FoxPro 或 SQL Server 不是很熟悉,所以在这方面我不能给你太多建议。

    但是,如果您找不到合适的驱动程序,您可以考虑自己解析原始数据和备忘录文件。另一个问题已经处理了这个问题:

    What's the easiest way to read a FoxPro DBF file from Python?

    信不信由你,如果您决定编写自己的 C# 解析器,这些文件格式的解析非常简单。这些规范可从 Microsoft 获得:

    【讨论】:

    • 谈谈让事情变得棘手 - 在 .NET 中有几种方法可以打开 FoxPro 表 - 通过 Access 进行链接很简单......
    • @Matt:也许您应该将其发布为答案?
    【解决方案3】:

    我使用 ODBC 链接 VFP 8 表,并且备注字段可以正常工作。不知道OLEDB是不是不一样。

    这里可能没有 Visual FoxPro 表。许多 VFP 系统使用与它们替换的 FoxPro 2 或 dBase 应用程序相同的表。您可以查看文件头或尝试其他 ODBC 驱动程序之一,看看它们是否工作。

    【讨论】:

    • 还是没有运气。使用此连接字符串(当然是 string.Format()'d):“Driver={{Microsoft Visual FoxPro Driver}};SourceType=DBF;SourceDB={0};Exclusive=No; Collat​​e=Machine;NULL=NO;已删除=否;后台提取=否;"尝试正常查询,as left(column_name, 8000)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-09-26
    • 2018-11-28
    • 2023-04-07
    • 1970-01-01
    • 1970-01-01
    • 2011-05-25
    • 1970-01-01
    相关资源
    最近更新 更多