⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tabdatfile.cpp

📁 linux下一款GIS程序源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
// tabdatfile.cpp: implementation of the TABDATFile class.////////////////////////////////////////////////////////////////////////#include "tabdatfile.h"#include "ugk_errhandle.h"#include "ugk_memopr.h"#include "ugk_string.h"/********************************************************************** *                   TABDATFile::TABDATFile() *                   构造函数  $zgq * Constructor. **********************************************************************/TABDATFile::TABDATFile(){    m_fp = NULL;    m_pszFname = NULL;    m_eTableType = TABTableNative;    m_poHeaderBlock = NULL;    m_poRecordBlock = NULL;    m_pasFieldDef = NULL;    m_numFields = -1;    m_numRecords = -1;    m_nFirstRecordPtr = 0;    m_nBlockSize = 0;    m_nRecordSize = -1;    m_nCurRecordId = -1;    m_bCurRecordDeletedFlag = FALSE;    m_bWriteHeaderInitialized = FALSE;}/********************************************************************** *                   TABDATFile::~TABDATFile() *                   析构函数  $zgq * Destructor. **********************************************************************/TABDATFile::~TABDATFile(){    Close();}/********************************************************************** *                   TABDATFile::Open() * * Open a .DAT file, and initialize the structures to be ready to read * records from it. * * We currently support NATIVE and DBF tables for reading, and only * NATIVE tables for writing. * * Returns 0 on success, -1 on error. **********************************************************************/int TABDATFile::Open(const char *pszFname, const char *pszAccess,                     TABTableType eTableType /*=TABNativeTable*/){    int i;    if (m_fp)    {        UGKError(ET_Failure, UGKErr_FileIO,                 "Open() failed: object already contains an open file");        return -1;    }    /*-----------------------------------------------------------------     * Validate access mode and make sure we use binary access.     *----------------------------------------------------------------*/    if (EQUALN(pszAccess, "r", 1) && (eTableType==TABTableNative ||                                      eTableType==TABTableDBF)  )    {        m_eAccessMode = TABRead;        pszAccess = "rb";    }    else if (EQUALN(pszAccess, "w", 1) && eTableType==TABTableNative)    {        m_eAccessMode = TABWrite;        pszAccess = "wb";    }    else    {        UGKError(ET_Failure, UGKErr_FileIO,                 "Open() failed: access mode \"%s\" not supported", pszAccess);        return -1;    }    /*-----------------------------------------------------------------     * Open file for reading     *----------------------------------------------------------------*/    m_pszFname = UGKStrdup(pszFname);    m_fp = fopen(m_pszFname, pszAccess);    m_eTableType = eTableType;    if (m_fp == NULL)    {        UGKError(ET_Failure, UGKErr_FileIO,                 "Open() failed for %s", m_pszFname);        UGK_Free(m_pszFname);        m_pszFname = NULL;        return -1;    }    if (m_eAccessMode == TABRead)    {        /*------------------------------------------------------------         * READ ACCESS:         * Read .DAT file header (record size, num records, etc...)         * m_poHeaderBlock will be reused later to read field definition         *-----------------------------------------------------------*/        m_poHeaderBlock = new TABRawBinBlock(m_eAccessMode, TRUE);        m_poHeaderBlock->ReadFromFile(m_fp, 0, 32);  //从头开始读取前32个字节 $zgq        m_poHeaderBlock->ReadByte();       // Table type ??? 0x03        m_poHeaderBlock->ReadByte();       // Last update year        m_poHeaderBlock->ReadByte();       // Last update month        m_poHeaderBlock->ReadByte();       // Last update day        m_numRecords      = m_poHeaderBlock->ReadInt32();  //总记录数  $zgq        m_nFirstRecordPtr = m_poHeaderBlock->ReadInt16();          m_nRecordSize     = m_poHeaderBlock->ReadInt16();  //记录长度  $zgq        m_numFields = m_nFirstRecordPtr/32 - 1;        /*-------------------------------------------------------------         * Read the field definitions         * First 32 bytes field definition starts at byte 32 in file         *------------------------------------------------------------*/        m_pasFieldDef = (TABDATFieldDef*)UGK_Calloc(m_numFields,                                                    sizeof(TABDATFieldDef));        for(i=0; i<m_numFields; i++)        {            m_poHeaderBlock->GotoByteInFile((i+1)*32);            m_poHeaderBlock->ReadBytes(11, (UGKByte*)m_pasFieldDef[i].szName);            m_pasFieldDef[i].szName[10] = '\0';            m_pasFieldDef[i].cType = (char)m_poHeaderBlock->ReadByte();            m_poHeaderBlock->ReadInt32();       // Skip Bytes 12-15            m_pasFieldDef[i].byLength = m_poHeaderBlock->ReadByte();            m_pasFieldDef[i].byDecimals = m_poHeaderBlock->ReadByte();            m_pasFieldDef[i].eTABType = TABFUnknown;        }        /*-------------------------------------------------------------         * Establish a good record block size to use based on record size, and          * then create m_poRecordBlock         * Record block size has to be a multiple of record size.         *------------------------------------------------------------*/        m_nBlockSize = ((1024/m_nRecordSize)+1)*m_nRecordSize;        m_nBlockSize = MIN(m_nBlockSize, (m_numRecords*m_nRecordSize));        assert( m_poRecordBlock == NULL );        m_poRecordBlock = new TABRawBinBlock(m_eAccessMode, FALSE);        m_poRecordBlock->InitNewBlock(m_fp, m_nBlockSize);        m_poRecordBlock->SetFirstBlockPtr(m_nFirstRecordPtr);    }    else    {        /*------------------------------------------------------------         * WRITE ACCESS:         * Set acceptable defaults for all class members.         * The real header initialization will be done when the first         * record is written         *-----------------------------------------------------------*/        m_poHeaderBlock = NULL;        m_numRecords      = 0;        m_nFirstRecordPtr = 0;        m_nRecordSize     = 0;        m_numFields = 0;        m_pasFieldDef = NULL;        m_bWriteHeaderInitialized = FALSE;    }    return 0;}/********************************************************************** *                   TABDATFile::Close() * * Close current file, and release all memory used. * * Returns 0 on success, -1 on error. **********************************************************************/int TABDATFile::Close(){    if (m_fp == NULL)        return 0;    /*----------------------------------------------------------------     * Write access: Update the header with number of records, etc.     * and add a CTRL-Z char at the end of the file.     *---------------------------------------------------------------*/    if (m_eAccessMode == TABWrite)    {        WriteHeader();        char cEOF = 26;        if (fseek(m_fp, 0L, SEEK_END) == 0)            fwrite(&cEOF, 1, 1, m_fp);    }        // Delete all structures     if (m_poHeaderBlock)    {        delete m_poHeaderBlock;        m_poHeaderBlock = NULL;    }    if (m_poRecordBlock)    {        delete m_poRecordBlock;        m_poRecordBlock = NULL;    }    // Close file    fclose(m_fp);    m_fp = NULL;    UGK_Free(m_pszFname);    m_pszFname = NULL;    UGK_Free(m_pasFieldDef);    m_pasFieldDef = NULL;    m_numFields = -1;    m_numRecords = -1;    m_nFirstRecordPtr = 0;    m_nBlockSize = 0;    m_nRecordSize = -1;    m_nCurRecordId = -1;    m_bWriteHeaderInitialized = FALSE;    return 0;}/********************************************************************** *                   TABDATFile::InitWriteHeader() * * Init the header members to be ready to write the header and data records * to a newly created data file. * * Returns 0 on success, -1 on error. **********************************************************************/int  TABDATFile::InitWriteHeader(){    int i;    if (m_eAccessMode != TABWrite || m_bWriteHeaderInitialized)        return 0;    /*------------------------------------------------------------     * Compute values for Record size, header size, etc.     *-----------------------------------------------------------*/    m_nFirstRecordPtr = (m_numFields+1)*32 + 1;    m_nRecordSize = 1;    for(i=0; i<m_numFields; i++)    {        m_nRecordSize += m_pasFieldDef[i].byLength;    }    /*-------------------------------------------------------------     * Create m_poRecordBlock the size of a data record.     *------------------------------------------------------------*/    m_nBlockSize = m_nRecordSize;    assert( m_poRecordBlock == NULL );    m_poRecordBlock = new TABRawBinBlock(m_eAccessMode, FALSE);    m_poRecordBlock->InitNewBlock(m_fp, m_nBlockSize);    m_poRecordBlock->SetFirstBlockPtr(m_nFirstRecordPtr);    /*-------------------------------------------------------------     * Make sure this init. will be performed only once     *------------------------------------------------------------*/    m_bWriteHeaderInitialized = TRUE;    return 0;}/********************************************************************** *                   TABDATFile::WriteHeader() * * Init the header members to be ready to write the header and data records * to a newly created data file. * * Returns 0 on success, -1 on error. **********************************************************************/int  TABDATFile::WriteHeader(){    int i;    if (m_eAccessMode != TABWrite)    {        UGKError(ET_Failure, UGKErr_NotSupported,                 "WriteHeader() can be used only with Write access.");        return -1;    }    if (!m_bWriteHeaderInitialized)        InitWriteHeader();    /*------------------------------------------------------------     * Create a single block that will be used to generate the whole header.     *-----------------------------------------------------------*/    if (m_poHeaderBlock == NULL)        m_poHeaderBlock = new TABRawBinBlock(m_eAccessMode, TRUE);    m_poHeaderBlock->InitNewBlock(m_fp, m_nFirstRecordPtr, 0);    /*------------------------------------------------------------     * First 32 bytes: main header block     *-----------------------------------------------------------*/    m_poHeaderBlock->WriteByte(0x03);  // Table type ??? 0x03    // __TODO__ Write the correct update date value    m_poHeaderBlock->WriteByte(99);    // Last update year    m_poHeaderBlock->WriteByte(9);     // Last update month    m_poHeaderBlock->WriteByte(9);     // Last update day    m_poHeaderBlock->WriteInt32(m_numRecords);    m_poHeaderBlock->WriteInt16(m_nFirstRecordPtr);    m_poHeaderBlock->WriteInt16(m_nRecordSize);    m_poHeaderBlock->WriteZeros(20);    // Pad rest with zeros    /*-------------------------------------------------------------     * Field definitions follow.  Each field def is 32 bytes.     *------------------------------------------------------------*/    for(i=0; i<m_numFields; i++)    {        m_poHeaderBlock->WriteBytes(11, (UGKByte*)m_pasFieldDef[i].szName);        m_poHeaderBlock->WriteByte(m_pasFieldDef[i].cType);        m_poHeaderBlock->WriteInt32(0);       // Skip Bytes 12-15        m_poHeaderBlock->WriteByte(m_pasFieldDef[i].byLength);        m_poHeaderBlock->WriteByte(m_pasFieldDef[i].byDecimals);        m_poHeaderBlock->WriteZeros(14);    // Pad rest with zeros    }    /*-------------------------------------------------------------     * Header ends with a 0x0d character.     *------------------------------------------------------------*/    m_poHeaderBlock->WriteByte(0x0d);    /*-------------------------------------------------------------     * Write the block to the file and return.     *------------------------------------------------------------*/    return m_poHeaderBlock->CommitToFile();}/********************************************************************** *                   TABDATFile::GetNumFields() * * Return the number of fields in this table. * * Returns a value >= 0 on success, -1 on error. **********************************************************************/int  TABDATFile::GetNumFields(){    return m_numFields;}/********************************************************************** *                   TABDATFile::GetNumRecords() * * Return the number of records in this table. * * Returns a value >= 0 on success, -1 on error. **********************************************************************/int  TABDATFile::GetNumRecords(){    return m_numRecords;}/********************************************************************** *                   TABDATFile::GetRecordBlock() * * Return a TABRawBinBlock reference positioned at the beginning of the * specified record and ready to read (or write) field values from/to it. * In read access, the returned block is guaranteed to contain at least one * full record of data, and in write access, it is at least big enough to * hold one full record. *  * Note that record ids are positive and start at 1. * * In Write access, CommitRecordToFile() MUST be called after the * data items have been written to the record, otherwise the record  * will never make it to the file. * * Returns a reference to the TABRawBinBlock on success or NULL on error. * The returned pointer is a reference to a block object owned by this  * TABDATFile object and should not be freed by the caller. **********************************************************************/TABRawBinBlock *TABDATFile::GetRecordBlock(int nRecordId){    m_bCurRecordDeletedFlag = FALSE;    if (m_eAccessMode == TABRead)    {        /*-------------------------------------------------------------         * READ ACCESS         *------------------------------------------------------------*/        int nFileOffset;        nFileOffset = m_nFirstRecordPtr+(nRecordId-1)*m_nRecordSize;        /*-------------------------------------------------------------         * Move record block pointer to the right location         *------------------------------------------------------------*/        if ( m_poRecordBlock == NULL ||              nRecordId < 1 || nRecordId > m_numRecords ||             m_poRecordBlock->GotoByteInFile(nFileOffset) != 0 )        {            UGKError(ET_Failure, UGKErr_FileIO,                     "Failed reading .DAT record block for record #%d in %s",                     nRecordId, m_pszFname);            return NULL;        }        /*-------------------------------------------------------------         * The first char of the record is a ' ' for an active record, or         * '*' for a deleted one.         * In the case of a deleted record, we simply return default         * values for each attribute... this is what MapInfo seems to do         * when it takes a .TAB with deleted records and exports it to .MIF         *------------------------------------------------------------*/        if (m_poRecordBlock->ReadByte() != ' ')        {            m_bCurRecordDeletedFlag = TRUE;        }    }    else if (m_eAccessMode == TABWrite && nRecordId > 0)    {        /*-------------------------------------------------------------         * WRITE ACCESS         *------------------------------------------------------------*/        int nFileOffset;        /*-------------------------------------------------------------         * Before writing the first record, we must generate the file          * header.  We will also initialize class members such as record         * size, etc. and will create m_poRecordBlock.         *------------------------------------------------------------*/        if (!m_bWriteHeaderInitialized)        {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -