代码之家  ›  专栏  ›  技术社区  ›  Jonathan DeMarks

如何使用.NET提取FoxPro备忘录字段中的数据?

  •  2
  • Jonathan DeMarks  · 技术社区  · 17 年前

    我正在编写一个C程序,将FoxPro数据库转换为XML,除“备注”字段为空外,一切都正常。有没有什么东西我想转换一下?

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

    当我将FoxPro数据库转换为SQL Server时,那里的“备注”字段也是空白的,因此我不能转换两次。

    3 回复  |  直到 11 年前
        1
  •  3
  •   Jonathan DeMarks    17 年前

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

            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文档非常简单)。

        2
  •  1
  •   Community Mohan Dere    9 年前

    我对C或FoxPro或SQL Server不太熟悉,因此在这方面我不能给您太多建议。

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

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

    信不信由你,如果你决定编写自己的C解析器,这些文件格式很容易解析。这些规范可从Microsoft获得:

        3
  •  1
  •   geoff franklin    17 年前

    我使用ODBC链接vfp 8表,而memo字段工作正常。我不知道OLEDB是否不同。

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