65.9K
CodeProject 正在变化。 阅读更多。
Home

在C#中生成PDB文件

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.20/5 (12投票s)

2006 年 1 月 10 日

GPL3

2分钟阅读

viewsIcon

171798

downloadIcon

1647

本文展示了如何创建 .pdb 文件,以便在 Palm 设备上用作数据库。

PDB Generator

Palm 数据库的基础知识

Palm 设备使用两种类型的数据库文件:PRC 和 PDB(即.prc.pdb)。PRC 用于 Palm OS 数据库,它是应用程序,并存储应用程序的资源,而 PDB(Pilot 数据库)用于仅包含数据的 Palm OS 数据库。这两种数据库都有一个唯一的密钥,每个应用程序都是唯一的。这些数据库可以像流读取和流写入一样进行操作。它包含一个名为“备份位”的属性位。设置此位表示没有自定义导管将备份数据库,并且应该在 HotSync 过程中备份数据库。如果在 Palm Pilot 上创建数据库并设置了“备份位”,则会在执行 HotSync 的计算机上的Backup目录中找到 PDB 格式的数据库副本。

此应用程序读取 CSV 或 XML 文件,并创建一个 .pdb 文件。

PDB 文件的主要部分

PDB 文件格式包含三个部分

  1. 头部部分
  2. 记录列表部分
  3. 数据列表部分

i. 头部部分

头部部分包含 78 个字节,包含数据库的名称和其他信息。此外,还包含对应用程序唯一的数据库 ID(该 ID 是全局唯一的,可以从 Palm OS 站点获得)、数据库的类型和其他属性。 PDBHeader 类用于创建头部。

class PDBHeader
{
    #region Declarations
    char[] databaseName={'\0','\0','\0','\0','\0','\0','\0', 
                         '\0','\0','\0','\0','\0','\0','\0','\0',
                         '\0','\0','\0','\0','\0','\0','\0','\0',
                         '\0','\0','\0','\0','\0','\0','\0',
                         '\0','\0'};   // 32 Bytes

    UInt16 fileAttributes = 0X0008;    // 2 Bytes
    UInt16 version = 0X0000;           // 2 Bytes
    UInt32 creationDate;               // 4 Bytes
    UInt32 modificationDate;           // 4 Bytes
    UInt32 lastBackupDate;             // 4 Bytes
    UInt32 modification=0X0000;        // 4 Bytes
    UInt32 appInfoArea=0X0000;         // 4 Bytes
    UInt32 sortInfoArea=0X0000;        // 4 Bytes
    char[]  type={'d','a','t','a'};    // 4 Bytes
    char[]  creatorID;                 // 4 Bytes
    UInt32 uniqueID=0X0000;            // 4 Bytes
    UInt32 nextRecord=0X0000;          // 4 Bytes
    UInt16 numRecords;                 // 2 Bytes
    #endregion 

    #region Properties
    public UInt16 NumRecords
    {
        set
        {
            numRecords=value;
        }
        get
        {
            return numRecords;
        }
    }
    public DateTime CreationDate
    {
        set
        {
            TimeSpan ts=DateTime.Now-value;
            creationDate=(UInt32)ts.TotalSeconds;
        }
    }
    public DateTime ModificationDate
    {
        set
        {
            TimeSpan ts=DateTime.Now-value;
            modificationDate=(UInt32)ts.TotalSeconds;
        }
    }
    public DateTime LastBackupDate
    {
        set
        {
            TimeSpan ts=DateTime.Now-value;
            lastBackupDate=(UInt32)ts.TotalSeconds;
        }
    }

    public string CreatorID
    {
        set
        {
            if (value.Length==4)
            {
                creatorID=value.ToCharArray();
            }
            else
            {
                throw new PDBException("Creator ID" + 
                  " is invalid (must be 4 charactors)");;
            }
        }
        get
        {
            return new String(creatorID);
        }
    }

    public string DataBaseName
    {
        set
        {
            if (value.Length<=32)
            {
                databaseName=value.ToCharArray();
            }
            else
            {
                
                throw new PDBException("Database Name" + 
                             " Exceeds 32 Charactors");;
            }
        }
        get
        {
            return new String(databaseName);
        }
    }

    #endregion 

    #region Functions

    public PDBHeader()
    {
        // Palm databse store total number
        // of seconds since 01-01-1904
        TimeSpan ts=
          DateTime.Now-DateTime.Parse("01-01-1904");
        creationDate=(UInt32)ts.TotalSeconds;
        modificationDate=(UInt32)ts.TotalSeconds;
        lastBackupDate=(UInt32)ts.TotalSeconds;
        numRecords=0;
    }

    public override string ToString()
    {
        string getAll="";
        getAll+=HexEncoding.GetStringToChar(databaseName,32);
        getAll+=fileAttributes.ToString("X4");
        getAll+=version.ToString("X4");
        getAll+=creationDate.ToString("X8");
        getAll+=modificationDate.ToString("X8");
        
        
        getAll+=lastBackupDate.ToString("X8");        
        getAll+=modification.ToString("X8");
        getAll+=appInfoArea.ToString("X8");    
        getAll+=sortInfoArea.ToString("X8");
        getAll+=HexEncoding.GetStringToChar(type,4);
        getAll+=HexEncoding.GetStringToChar(creatorID,4);
        getAll+=uniqueID.ToString("X8");
        getAll+=nextRecord.ToString("X8");
        getAll+=numRecords.ToString("X4");

        return getAll;
    }

ii. 记录列表部分

记录列表部分的大小取决于记录的数量。每个记录使用 8 位来存储记录信息。 PDBRecordList 类用于表示记录列表。

class PDBRecordList
{
    #region Declarations
    UInt32 offset=0;   // 4 Bytes (Offset of the record)
    byte recordAttribute=0X40;
    char[] uniqueID={'\0','\0','\0'}; // 3 Bytes (Unique ID for each record)
    string dataRecord=""; // Record data for current record
    #endregion 

    #region Properties
    public string DataRecord
    {
        set
        {
            dataRecord=value;
        }
        get
        {
            return dataRecord;
        }
    }
    public UInt32 RecordOffset
    {
        set
        {
            offset=value;
        }
        get
        {
            return offset;
        }
    }
    #endregion 

    #region Functions
    public PDBRecordList(string str)
    {
        dataRecord=str;
    }
    public override string ToString()
    {

        string getAll="";
        getAll+=offset.ToString("X8");
        getAll+=recordAttribute.ToString("X2");        
        getAll+=HexEncoding.GetStringToChar(uniqueID,3);
        return getAll;
    }

    #endregion
}

iii. 数据部分

它是存储与记录相关的信息的主要部分。每条记录都以空终止字符('\0')分隔。每个记录的大小可能不同,但列数应相同。

使用代码

PDBCreators 类用于创建数据库。

class PDBCreators
{
    PDBHeader header=new PDBHeader();
    ArrayList pdbRecord=new ArrayList();
    public PDBCreators()
    {
    }
    public PDBHeader PDBHeaders
    {
        set
        {
            header=value;
        }
        get
        {
            return header;
        }
    }
    public Object[] AddRecord
    {
        set
        {
            string row="";
            for (int i=0; i<value.Length; i++)
            {
                if (value[i].GetType().ToString()=="System.Int32")  
                    continue;
                row+=value[i].ToString().Trim()+'\0';
            }
            pdbRecord.Add(new PDBRecordList(row));
        }
    }

    public void GeneratePDB(string fileName)
    {
        try
        {
            FileStream fs=new FileStream(fileName,FileMode.Create);
            BinaryWriter bw=new BinaryWriter(fs);
            int discard=0;
            UInt32 index=78;     // Header length is 78 Bytes
            header.NumRecords=(UInt16)pdbRecord.Count;

            bw.Write(HexEncoding.GetBytes(header.ToString(), 
                                              out discard));

            // start index of Data List Area
            index+=(UInt32)(pdbRecord.Count*8)+2;
            string result="";
            for (int i=0; ipdbRecord.Count; i++)
            {
                PDBRecordList rec=(PDBRecordList)pdbRecord[i];
                rec.RecordOffset=index;
                bw.Write(HexEncoding.GetBytes(rec.ToString(), 
                                               out discard));
                index+=(UInt32)rec.DataRecord.Length;
                result+=rec.DataRecord;
            }
            char[] padding={'\0','\0'};  // Two bytes for backup bits
            bw.Write(HexEncoding.GetBytes(
              HexEncoding.GetStringToChar(padding,2), 
              out discard));
            result=HexEncoding.GetStringToChar(
              result.ToCharArray(),result.Length);
            bw.Write(HexEncoding.GetBytes(result,out discard));
            bw.Close();
            fs.Close();
        }
        catch (Exception exc)
        {
            throw new PDBException("Error" + 
              " in writing pdb file "+exc.Message);
        }

    }
}

PDBGenerator 读取两种文件格式(CSV 和 XML),并在 DataGrid 中以表格格式显示数据。可以更改此数据。它从 XML 文件中读取所有表格数据,并在组合框中显示表格名称。

PDBCreators pdb=new PDBCreators();
pdb.PDBHeaders.DataBaseName=this.txtDBName.Text;
pdb.PDBHeaders.CreatorID=this.txtCreatorID.Text;

DataTable recordsTable;
if (recordsDataSet.Tables.Count>0 && 
        this.cmbTableNames.Items.Count>0 && 
        recordsDataSet.Tables.Contains(this.cmbTableNames.Text))
    recordsTable=recordsDataSet.Tables[this.cmbTableNames.Text];
else
{
    MessageBox.Show("There is no table to convert", 
          "PDB Generator",MessageBoxButtons.OK,
          MessageBoxIcon.Information);
    return;
}
for (int i=0; i<recordsTable.Rows.Count; i++)
    pdb.AddRecord=recordsTable.Rows[i].ItemArray;
try
{
    pdb.GeneratePDB(this.txtDestination.Text+"\\"+
                      this.txtDBName.Text+".pdb");
    MessageBox.Show("PDB Generated Successfully",
      "PDB Generator",MessageBoxButtons.OK,
      MessageBoxIcon.Information);
}
catch(Exception exc)
{
    MessageBox.Show("Error in PDB Generation"+exc.ToString(),
      "PDB Generator",MessageBoxButtons.OK,
      MessageBoxIcon.Information);
}
© . All rights reserved.