Acerca de cómo usar C ++ para leer archivos .dbf

formato de archivo .dbf

La descripción del formato de archivo .dbf se puede encontrar en estos dos blogs:

  1. Formato de archivo DBF
  2. serie shp (tres)

No entraré en detalles sobre el formato de archivo dbf, porque los dos blogs anteriores ya han hablado muy claramente. Este artículo trata principalmente sobre cómo leer archivos .dbf arbitrarios a través de C ++.

Código C ++

1.clase de campo

.dbf es un archivo de tabla, que se almacena en modo binario, y el archivo de encabezado es de longitud variable.
Dado que es un archivo de tabla, existe un concepto de rangos. Las filas de la tabla DBF se representan como registros y las columnas se representan como campos. Por lo tanto, puede diseñar una clase de campo, a saber, Class Field.
el código se muestra a continuación:

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

La clase DBaseFIle contiene el contenido del encabezado del archivo y el contenido de todos los campos.
El código del archivo de encabezado es el siguiente:

/********************************************************************************
 * 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. Realización 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)
{
    
    }

para resumir

Este artículo comienza con el formato de archivo DBF, la clase de campo abstracto y la clase DBaseFile, el código tiene un cierto grado de versatilidad, para archivos DBF en circunstancias normales, se puede leer el código de este artículo. Sin embargo, este artículo solo lee el archivo DBF en la memoria y no implica la operación de escritura del archivo, por lo que tiene ciertas limitaciones. Pero para el formato de archivo DBF, el código de este artículo puede ayudar a los lectores a comprender.

Supongo que te gusta

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