Sobre como usar C ++ para ler arquivos .dbf

formato de arquivo .dbf

A descrição do formato de arquivo .dbf pode ser encontrada nestes dois blogs:

  1. Formato de arquivo DBF
  2. série shp (três)

Não vou entrar em detalhes sobre o formato de arquivo dbf, pois os dois blogs acima já conversaram muito claramente. Este artigo é principalmente sobre como ler arquivos .dbf arbitrários em C ++.

Código C ++

1. Classe de campo

.dbf é um arquivo de tabela, que é armazenado em modo binário, e o arquivo de cabeçalho tem comprimento variável.
Por ser um arquivo de tabela, existe um conceito de classificação. As linhas da tabela DBF são representadas como registros e as colunas são representadas como campos. Portanto, você pode criar uma classe de campo, ou seja, Class Field.
código mostrado como abaixo:

/********************************************************************************
 * 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. Classe DBaseFile

A classe DBaseFIle contém o conteúdo do cabeçalho do arquivo e o conteúdo de todos os campos.
O código do arquivo de cabeçalho é o seguinte:

/********************************************************************************
 * 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. Realização concreta

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)
{
    
    }

Resumindo

Este artigo parte do formato de arquivo DBF, classe abstrata Field e classe DBaseFile, o código tem um certo grau de versatilidade, para arquivos DBF em circunstâncias normais, o código deste artigo pode ser lido. No entanto, este artigo apenas lê o arquivo DBF na memória e não envolve a operação de gravação do arquivo, portanto, tem certas limitações. Mas para o formato de arquivo DBF, o código neste artigo pode ajudar os leitores a entender.

Acho que você gosta

Origin blog.csdn.net/GeomasterYi/article/details/106635440
Recomendado
Clasificación