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

📄 mitab_datfile.cpp

📁 用于读取TAB、MIF、SHP文件的类
💻 CPP
📖 第 1 页 / 共 4 页
字号:
    }    /*-------------------------------------------------------------     * Create m_poRecordBlock the size of a data record.     *------------------------------------------------------------*/    m_nBlockSize = m_nRecordSize;    CPLAssert( 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)    {        CPLError(CE_Failure, CPLE_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, (GByte*)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 )        {            CPLError(CE_Failure, CPLE_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)        {            WriteHeader();        }        m_numRecords = MAX(nRecordId, m_numRecords);        nFileOffset = m_nFirstRecordPtr+(nRecordId-1)*m_nRecordSize;        m_poRecordBlock->InitNewBlock(m_fp, m_nRecordSize, nFileOffset);        /*-------------------------------------------------------------         * The first char of the record is the active/deleted flag.         * Automatically set it to ' ' (active).         *------------------------------------------------------------*/        m_poRecordBlock->WriteByte(' ');    }    m_nCurRecordId = nRecordId;    return m_poRecordBlock;}/********************************************************************** *                   TABDATFile::CommitRecordToFile() * * Commit the data record previously initialized with GetRecordBlock() * to the file.  This function must be called after writing the data * values to a record otherwise the record will never make it to the * file. * * Returns 0 on success, -1 on error. **********************************************************************/int  TABDATFile::CommitRecordToFile(){    if (m_eAccessMode != TABWrite || m_poRecordBlock == NULL)        return -1;    return m_poRecordBlock->CommitToFile();}/********************************************************************** *                   TABDATFile::ValidateFieldInfoFromTAB() * * Check that the value read from the .TAB file by the caller are  * consistent with what is found in the .DAT header. * * Note that field ids are positive and start at 0. * * We have to use this function when opening a file for reading since  * the .DAT file does not contain the full field types information... * a .DAT file is actually a .DBF file in which the .DBF types are * handled in a special way... type 'C' fields are used to store binary  * values for most MapInfo types. * * For TABTableDBF, we actually have no validation to do since all types * are stored as strings internally, so we'll just convert from string. * * Returns a value >= 0 if OK, -1 on error. **********************************************************************/int  TABDATFile::ValidateFieldInfoFromTAB(int iField, const char *pszName,                                          TABFieldType eType,                                          int nWidth, int nPrecision){    int i = iField;  // Just to make things shorter    CPLAssert(m_pasFieldDef);    if (m_pasFieldDef == NULL || iField < 0 || iField >= m_numFields)    {        CPLError(CE_Failure, CPLE_FileIO,          "Invalid field %d (%s) in .TAB header. %s contains only %d fields.",                 iField+1, pszName, m_pszFname, m_pasFieldDef? m_numFields:0);        return -1;    }    /*-----------------------------------------------------------------     * We used to check that the .TAB field name matched the .DAT     * name stored internally, but apparently some tools that rename table     * field names only update the .TAB file and not the .DAT, so we won't     * do that name validation any more... we'll just check the type.     *     * With TABTableNative, we have to validate the field sizes as well     * because .DAT files use char fields to store binary values.     * With TABTableDBF, no need to validate field type since all     * fields are stored as strings internally.     *----------------------------------------------------------------*/    if ((m_eTableType == TABTableNative &&          ((eType == TABFChar && (m_pasFieldDef[i].cType != 'C' ||                                m_pasFieldDef[i].byLength != nWidth )) ||          (eType == TABFDecimal && (m_pasFieldDef[i].cType != 'N' ||                                  m_pasFieldDef[i].byLength != nWidth||                                   m_pasFieldDef[i].byDecimals!=nPrecision)) ||          (eType == TABFInteger && (m_pasFieldDef[i].cType != 'C' ||                                   m_pasFieldDef[i].byLength != 4  )) ||          (eType == TABFSmallInt && (m_pasFieldDef[i].cType != 'C' ||                                    m_pasFieldDef[i].byLength != 2 )) ||          (eType == TABFFloat && (m_pasFieldDef[i].cType != 'C' ||                                 m_pasFieldDef[i].byLength != 8    )) ||          (eType == TABFDate && (m_pasFieldDef[i].cType != 'C' ||                                m_pasFieldDef[i].byLength != 4     )) ||          (eType == TABFLogical && (m_pasFieldDef[i].cType != 'L' ||                                   m_pasFieldDef[i].byLength != 1  ))   ) ))    {        CPLError(CE_Failure, CPLE_FileIO,                 "Definition of field %d (%s) from .TAB file does not match "                 "what is found in %s (name=%s, type=%c, width=%d, prec=%d)",                 iField+1, pszName, m_pszFname,                 m_pasFieldDef[i].szName, m_pasFieldDef[i].cType,                  m_pasFieldDef[i].byLength, m_pasFieldDef[i].byDecimals);        return -1;    }    m_pasFieldDef[i].eTABType = eType;    return 0;}/********************************************************************** *                   TABDATFile::AddField() * * Create a new field (column) in a newly created table.  This function * must be called after the file has been opened, but before writing the * first record. * * Returns the new field index (a value >= 0) if OK, -1 on error. **********************************************************************/int  TABDATFile::AddField(const char *pszName, TABFieldType eType,                          int nWidth, int nPrecision /*=0*/){    if (m_eAccessMode != TABWrite || m_bWriteHeaderInitialized ||        m_eTableType != TABTableNative)    {        CPLError(CE_Failure, CPLE_NotSupported,                 "Addition of new table fields is not supported after the "                 "first data item has been written.");        return -1;    }    /*-----------------------------------------------------------------     * Validate field width... must be <= 254     *----------------------------------------------------------------*/    if (nWidth > 254)    {        CPLError(CE_Failure, CPLE_IllegalArg,                 "Invalid size (%d) for field '%s'.  "                 "Size must be 254 or less.", nWidth, pszName);        return -1;    }    /*-----------------------------------------------------------------     * Map fields with width=0 (variable length in OGR) to a valid default     *----------------------------------------------------------------*/    if (eType == TABFDecimal && nWidth == 0)        nWidth=20;    else if (nWidth == 0)        nWidth=254; /* char fields */    if (m_numFields < 0)        m_numFields = 0;    m_numFields++;    m_pasFieldDef = (TABDATFieldDef*)CPLRealloc(m_pasFieldDef,                                           m_numFields*sizeof(TABDATFieldDef));    strncpy(m_pasFieldDef[m_numFields-1].szName, pszName, 10);    m_pasFieldDef[m_numFields-1].szName[10] = '\0';    m_pasFieldDef[m_numFields-1].eTABType = eType;    m_pasFieldDef[m_numFields-1].byLength = (GByte)nWidth;    m_pasFieldDef[m_numFields-1].byDecimals = (GByte)nPrecision;

⌨️ 快捷键说明

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