C ++を使用して.dbfファイルを読み取る方法について

.dbfファイル形式

.dbfファイル形式の説明は、次の2つのブログにあります。

  1. DBFファイル形式
  2. shpシリーズ(3)

上記の2つのブログではすでに非常に明確に説明されているため、dbfファイル形式の詳細については説明しません。この記事は主に、C ++を介して任意の.dbfファイルを読み取る方法について説明しています。

C ++コード

1.フィールドクラス

.dbfはバイナリモードで保存されるテーブルファイルであり、ヘッダーファイルは可変長です。
テーブルファイルなので、ランクの概念があります。DBFテーブルの行はレコードとして表され、列はフィールドとして表されます。したがって、フィールドクラス、つまりクラスフィールドを設計できます。
コードは次のように表示されます。

/********************************************************************************
 * Description: this header file is designed for reading and saving 
 *              the field in the dBaseFile
 * 
 * Author: Mr.Zhang Wanglin(Geocat)
 * 
 * Date: 2020.06.07
********************************************************************************/

#ifndef FIELD_H
#define FIELD_H

#include <vector>
using std::vector;

class Field
{
    
    
public:
    Field();

    void storeFieldContent();

    enum _eRecordItemDataType{
    
    B,C,D,G,L,M,N};  // 记录项的数据类型

    // 属性—— 1. 文件头中字段的内容:32字节

        // 0-10字节为记录项(字段)名称
    char _cTitle[11];

        // 11字节为记录项的数据类型
    char _cDataType;

        // 16字节为记录项长度,BYTE类型,1个字节
            // 注:可以用强制类型转换将记录项长度转换成int型
    unsigned char _ucFieldLength;

        // 字段内容
    char _cFieldContent[100];

    vector<char*> _vField;  // 存储字段的内容
};

#endif // FIELD_H

2.DBaseFileクラス

DBaseFIleクラスには、ファイルヘッダーの内容とすべてのフィールドの内容が含まれています。
ヘッダーファイルのコードは次のとおりです。

/********************************************************************************
 * Description: this header file is designed for reading and saving
 *              the field in the dBaseFile
 *
 * Author: Mr.Zhang Wanglin(Geocat)
 *
 * Date: 2020.06.08
********************************************************************************/
#ifndef DBASEFILE_H
#define DBASEFILE_H

#include <string>
#include <vector>
#include <fstream>
#include "field.h"

using namespace std;

class DBaseFile
{
    
    
public:
    // 构造函数
    DBaseFile();
    DBaseFile(string sFilename);

    // 自定义函数
        // loadFile(string)函数将文件读取到内存
    void loadFile(string sFilename);
    void showData();

    // 数据表的增删改查
    void addRec(int iColum, int iLine, unsigned char* ucData);
    void deleteRec(int iColum, int iLine, unsigned char* ucData);
    void modifyRec(int iColum, int iLine, unsigned char* ucData);
    void checkRec(int iColum, int iLine, unsigned char* ucData);

    // 属性
        // 文件头中的内容
    int _iRecCount; // 记录的条数——行数
    int _iFieldCount;   // 字段数——列数
    short _BytesOfFileHead; // 文件头中的字节数
    short _BytesOfEachRecord;   // 每一条记录的字节数

        // 内存中用来存储相应数据的变量
    Field* _pField; // 用来创建某个字段
    string _sFilename;  // 用来存储文件名
//    vector<char*> _vFieldNameInFileHead;   // 文件头中的字段名
    vector<Field*> _vTable;  // 用来存储所有的字段的内容,是一个存储字段容器

protected:
    void readFileHead(ifstream& inFile);
    void readFileRecord(ifstream& inFile);
    bool isReadFileOK(string sFilename);
};

#endif // DBASEFILE_H

3.具体的な実現

field.cpp

#include "field.h"

Field::Field()
{
    
    

}

void Field:: storeFieldContent()
{
    
    
    _vField.push_back(_cFieldContent);
}

dbasefile.cpp

#include "dbasefile.h"
#include <iostream>

DBaseFile::DBaseFile()
{
    
    }

DBaseFile::DBaseFile(string sFilename)
{
    
    
    this->_sFilename=sFilename;
}

void DBaseFile:: loadFile(string sFilename)
{
    
    
    ifstream inFile(sFilename,ios::binary|ios::in);

    if(!isReadFileOK(sFilename))
        return;
    readFileHead(inFile);
    readFileRecord(inFile);
    inFile.close();
}

void DBaseFile:: showData()
{
    
    
    for(unsigned int i=0;i<_vTable.size();i++)
    {
    
    
        cout<<_vTable[i]->_cTitle<<"\t";
    }
    cout<<"\n";
    for(int i=0;i<_iRecCount;i++)
    {
    
    
        for(unsigned int j=0;j<_vTable.size();j++)
            cout<<_vTable[j]->_vField[i]<<"\t";
        cout<<endl;
    }
}

bool DBaseFile::isReadFileOK(string sFilename)
{
    
    
    ifstream inFile(sFilename,ios::binary|ios::in);
    if(inFile.good())
    {
    
    
        inFile.close();
        return true;
    }
    else
        return false;
}

void DBaseFile:: readFileHead(ifstream& inFile)
{
    
    
    if(!isReadFileOK(_sFilename))
        return;
    // 读取文件头中的记录条数,即行数
    inFile.seekg(4,ios::beg);
    inFile.read((char*)&_iRecCount,sizeof (int));

    // 读取文件头的字节数
    inFile.read((char*)&_BytesOfFileHead,sizeof (short));

    // 读取一条记录中的字节长度
    inFile.read((char*)&_BytesOfEachRecord,sizeof (short));

    // 计算字段数,即列数
    _iFieldCount = (_BytesOfFileHead-33)/32;

    // 开始读取文件头中关于字段的描述
    for(int i=0;i<_iFieldCount;i++)
    {
    
    
        inFile.seekg(32+32*i,ios::beg);
        _pField=new Field;
        for(int j=0;j<11;j++)   // 读取字段名,存入_cTitle数组
            inFile.read(_pField->_cTitle+j,sizeof (char));
        inFile.read(&_pField->_cDataType,sizeof (char));    // 读取字段的数据类型并存入_cDataType
        inFile.seekg(4,ios::cur);
        inFile.read((char*)&_pField->_ucFieldLength,sizeof (char));    // 读取字段长度,此时的字段长度为BYTE类型,需通过强制类型转换成int型

        _vTable.push_back(_pField);
    }
}

void DBaseFile:: readFileRecord(ifstream& inFile)
{
    
    
    inFile.seekg(_BytesOfFileHead,ios::beg);
    char cDeleteTag;
    for(int i=0;i<_iRecCount;i++)
    {
    
    
        inFile.read(&cDeleteTag,sizeof (char));
        for(unsigned int j=0;j<_vTable.size();j++)
        {
    
    
            char*cRecord=new char[(int)_vTable[j]->_ucFieldLength];
            for(int k=0;k<(int)_vTable[j]->_ucFieldLength;k++)
                inFile.read(cRecord+k,sizeof (char));
            _vTable[j]->_vField.push_back(cRecord);
        }
    }
}

void DBaseFile:: addRec(int iColum, int iLine, unsigned char* ucData)
{
    
    }

void DBaseFile:: deleteRec(int iColum, int iLine, unsigned char* ucData)
{
    
    }

void DBaseFile:: modifyRec(int iColum, int iLine, unsigned char* ucData)
{
    
    }

void DBaseFile:: checkRec(int iColum, int iLine, unsigned char* ucData)
{
    
    }

総括する

この記事は、DBFファイル形式、抽象FieldクラスおよびDBaseFileクラスから始まります。コードにはある程度の汎用性があり、通常の状況でのDBFファイルの場合、この記事のコードを読むことができます。ただし、この記事ではDBFファイルをメモリに読み込むだけで、ファイルの書き込み操作は含まないため、一定の制限があります。ただし、DBFファイル形式の場合、この記事のコードは読者が理解するのに役立ちます。

おすすめ

転載: blog.csdn.net/GeomasterYi/article/details/106635440