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

📄 mitab_datfile.cpp

📁 mitab,读取MapInfo的地图文件
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    if (m_poRecordBlock == NULL)
    {
        CPLError(CE_Failure, CPLE_AssertionFailed,
                 "Can't read field value: file is not opened.");
        return "";
    }

    // With .DBF files, there is nothing to do... the value should already
    // be stored in HHMMSSMMM format according to DBF specs.
    if (m_eTableType == TABTableDBF)
        return ReadCharField(nWidth);


    nS  = m_poRecordBlock->ReadInt32(); // Convert time from ms to sec

    // nS is set to -1 when the value is 'not set'
    if (CPLGetLastErrorNo() != 0 || nS < 0 || (nS>86400000))
        return "";

    int nHour = int(nS/3600000);
    int nMin  = int((nS/1000 - nHour*3600)/60);
    int nSec  = int(nS/1000 - nHour*3600 - nMin*60);
    int nMS   = int(nS-nHour*3600000-nMin*60000-nSec*1000);
    sprintf(szBuf, "%2.2d%2.2d%2.2d%3.3d", nHour, nMin, nSec, nMS);

    return szBuf;
}

/**********************************************************************
 *                   TABDATFile::ReadDateTimeField()
 *
 * Read the DateTime field value at the current position in the data 
 * block.
 *
 * A datetime field is an 8 bytes binary value in which the first byte is
 * the day, followed by 1 byte for the month, and 2 bytes for the year. After
 * this is 4 bytes which represents the number of milliseconds since midnight.
 *
 * We return an 17 chars string in the format "YYYYMMDDhhmmssmmm"
 * 
 * Note: nWidth is used only with TABTableDBF types.
 *
 * Returns a reference to an internal buffer that will be valid only until
 * the next field is read, or "" if the operation failed, in which case
 * CPLError() will have been called.
 **********************************************************************/
const char *TABDATFile::ReadDateTimeField(int nWidth)
{
    int nDay, nMonth, nYear;
    GInt32 nS;
    static char szBuf[20];

    // If current record has been deleted, then return an acceptable 
    // default value.
    if (m_bCurRecordDeletedFlag)
        return "";

    if (m_poRecordBlock == NULL)
    {
        CPLError(CE_Failure, CPLE_AssertionFailed,
                 "Can't read field value: file is not opened.");
        return "";
    }

    // With .DBF files, there is nothing to do... the value should already
    // be stored in YYYYMMDD format according to DBF specs.
    if (m_eTableType == TABTableDBF)
        return ReadCharField(nWidth);


    nYear  = m_poRecordBlock->ReadInt16();
    nMonth = m_poRecordBlock->ReadByte();
    nDay   = m_poRecordBlock->ReadByte();
    nS     = m_poRecordBlock->ReadInt32();

    if (CPLGetLastErrorNo() != 0 || 
        (nYear==0 && nMonth==0 && nDay==0) || (nS>86400000))
        return "";

    int nHour = int(nS/3600000);
    int nMin  = int((nS/1000 - nHour*3600)/60);
    int nSec  = int(nS/1000 - nHour*3600 - nMin*60);
    int nMS   = int(nS-nHour*3600000-nMin*60000-nSec*1000);

    sprintf(szBuf, "%4.4d%2.2d%2.2d%2.2d%2.2d%2.2d%3.3d", 
            nYear, nMonth, nDay, nHour, nMin, nSec, nMS);

    return szBuf;
}

/**********************************************************************
 *                   TABDATFile::ReadDecimalField()
 *
 * Read the decimal field value at the current position in the data 
 * block.
 *
 * A decimal field is a floating point value with a fixed number of digits
 * stored as a character string.
 *
 * nWidth is the field length, as defined in the .DAT header.
 *
 * We return the value as a binary double.
 * 
 * CPLError() will have been called if something fails.
 **********************************************************************/
double TABDATFile::ReadDecimalField(int nWidth)
{
    const char *pszVal;

    // If current record has been deleted, then return an acceptable 
    // default value.
    if (m_bCurRecordDeletedFlag)
        return 0.0;

    pszVal = ReadCharField(nWidth);

    return atof(pszVal);
}


/**********************************************************************
 *                   TABDATFile::WriteCharField()
 *
 * Write the character field value at the current position in the data 
 * block.
 * 
 * Use GetRecordBlock() to position the data block to the beginning of
 * a record before attempting to write values.
 *
 * nWidth is the field length, as defined in the .DAT header.
 *
 * Returns 0 on success, or -1 if the operation failed, in which case
 * CPLError() will have been called.
 **********************************************************************/
int TABDATFile::WriteCharField(const char *pszStr, int nWidth,
                               TABINDFile *poINDFile, int nIndexNo)
{
    if (m_poRecordBlock == NULL)
    {
        CPLError(CE_Failure, CPLE_AssertionFailed,
            "Can't write field value: GetRecordBlock() has not been called.");
        return -1;
    }

    if (nWidth < 1 || nWidth > 255)
    {
        CPLError(CE_Failure, CPLE_AssertionFailed,
                 "Illegal width for a char field: %d", nWidth);
        return -1;
    }
    
    //
    // Write the buffer after making sure that we don't try to read
    // past the end of the source buffer.  The rest of the field will
    // be padded with zeros if source string is shorter than specified
    // field width.
    //
    int nLen = strlen(pszStr);
    nLen = MIN(nLen, nWidth);

    if ((nLen>0 && m_poRecordBlock->WriteBytes(nLen, (GByte*)pszStr) != 0) ||
        (nWidth-nLen > 0 && m_poRecordBlock->WriteZeros(nWidth-nLen)!=0) )
        return -1;

    // Update Index
    if (poINDFile && nIndexNo > 0)
    {
        GByte *pKey = poINDFile->BuildKey(nIndexNo, pszStr);
        if (poINDFile->AddEntry(nIndexNo, pKey, m_nCurRecordId) != 0)
            return -1;
    }

    return 0;
}

/**********************************************************************
 *                   TABDATFile::WriteIntegerField()
 *
 * Write the integer field value at the current position in the data 
 * block.
 * 
 * CPLError() will have been called if something fails.
 **********************************************************************/
int TABDATFile::WriteIntegerField(GInt32 nValue,
                                  TABINDFile *poINDFile, int nIndexNo)
{
    if (m_poRecordBlock == NULL)
    {
        CPLError(CE_Failure, CPLE_AssertionFailed,
            "Can't write field value: GetRecordBlock() has not been called.");
        return -1;
    }

    // Update Index
    if (poINDFile && nIndexNo > 0)
    {
        GByte *pKey = poINDFile->BuildKey(nIndexNo, nValue);
        if (poINDFile->AddEntry(nIndexNo, pKey, m_nCurRecordId) != 0)
            return -1;
    }

    return m_poRecordBlock->WriteInt32(nValue);
}

/**********************************************************************
 *                   TABDATFile::WriteSmallIntField()
 *
 * Write the smallint field value at the current position in the data 
 * block.
 * 
 * CPLError() will have been called if something fails.
 **********************************************************************/
int TABDATFile::WriteSmallIntField(GInt16 nValue,
                                   TABINDFile *poINDFile, int nIndexNo)
{
    if (m_poRecordBlock == NULL)
    {
        CPLError(CE_Failure, CPLE_AssertionFailed,
            "Can't write field value: GetRecordBlock() has not been called.");
        return -1;
    }

    // Update Index
    if (poINDFile && nIndexNo > 0)
    {
        GByte *pKey = poINDFile->BuildKey(nIndexNo, nValue);
        if (poINDFile->AddEntry(nIndexNo, pKey, m_nCurRecordId) != 0)
            return -1;
    }

    return m_poRecordBlock->WriteInt16(nValue);
}

/**********************************************************************
 *                   TABDATFile::WriteFloatField()
 *
 * Write the float field value at the current position in the data 
 * block.
 * 
 * CPLError() will have been called if something fails.
 **********************************************************************/
int TABDATFile::WriteFloatField(double dValue,
                                TABINDFile *poINDFile, int nIndexNo)
{
    if (m_poRecordBlock == NULL)
    {
        CPLError(CE_Failure, CPLE_AssertionFailed,
            "Can't write field value: GetRecordBlock() has not been called.");
        return -1;
    }

    // Update Index
    if (poINDFile && nIndexNo > 0)
    {
        GByte *pKey = poINDFile->BuildKey(nIndexNo, dValue);
        if (poINDFile->AddEntry(nIndexNo, pKey, m_nCurRecordId) != 0)
            return -1;
    }

    return m_poRecordBlock->WriteDouble(dValue);
}

/**********************************************************************
 *                   TABDATFile::WriteLogicalField()
 *
 * Write the logical field value at the current position in the data 
 * block.
 *
 * The value written to the file is either 0 or 1, but this function
 * takes as input a string with "F" (false) or "T" (true)
 * 
 * CPLError() will have been called if something fails.
 **********************************************************************/
int TABDATFile::WriteLogicalField(const char *pszValue,
                                  TABINDFile *poINDFile, int nIndexNo)
{
    GByte bValue;

    if (m_poRecordBlock == NULL)
    {
        CPLError(CE_Failure, CPLE_AssertionFailed,
            "Can't write field value: GetRecordBlock() has not been called.");
        return -1;
    }

    if (EQUALN(pszValue, "T", 1))
        bValue = 1;
    else
        bValue = 0;

    // Update Index
    if (poINDFile && nIndexNo > 0)
    {
        GByte *pKey = poINDFile->BuildKey(nIndexNo, (int)bValue);
        if (poINDFile->AddEntry(nIndexNo, pKey, m_nCurRecordId) != 0)
            return -1;
    }

    return m_poRecordBlock->WriteByte(bValue);
}

/**********************************************************************
 *                   TABDATFile::WriteDateField()
 *
 * Write the date field value at the current position in the data 
 * block.
 *
 * A date field is a 4 bytes binary value in which the first byte is
 * the day, followed by 1 byte for the month, and 2 bytes for the year.
 *
 * The expected input is a 10 chars string in the format "YYYY/MM/DD"
 * or "DD/MM/YYYY" or "YYYYMMDD"
 * 
 * Returns 0 on success, or -1 if the operation failed, in which case
 * CPLError() will have been called.
 **********************************************************************/
int TABDATFile::WriteDateField(const char *pszValue,
                               TABINDFile *poINDFile, int nIndexNo)
{
    int nDay, nMonth, nYear;
    char **papszTok = NULL;

    if (m_poRecordBlock == NULL)
    {
        CPLError(CE_Failure, CPLE_AssertionFailed,
            "Can't write field value: GetRecordBlock() has not been called.");
        return -1;
    }

    /*-----------------------------------------------------------------
     * Get rid of leading spaces.
     *----------------------------------------------------------------*/
    while ( *pszValue == ' ' ) { pszValue++; }

    /*-----------------------------------------------------------------
     * Try to automagically detect date format, one of:
     * "YYYY/MM/DD", "DD/MM/YYYY", or "YYYYMMDD"
     *----------------------------------------------------------------*/
    
    if (strlen(pszValue) == 8)
    {
        /*-------------------------------------------------------------
         * "YYYYMMDD"
         *------------------------------------------------------------*/
        char szBuf[9];
        strcpy(szBuf, pszValue);
        nDay = atoi(szBuf+6);
        szBuf[6] = '\0';
        nMonth = atoi(szBuf+4);
        szBuf[4] = '\0';
        nYear = atoi(szBuf);
    }
    else if (strlen(pszValue) == 10 &&
             (papszTok = CSLTokenizeStringComplex(pszValue, "/", 
                                                  FALSE, FALSE)) != NULL &&
             CSLCount(papszTok) == 3 &&
             (strlen(papszTok[0]) == 4 || strlen(papszTok[2]) == 4) )
    {
        /*-------------------------------------------------------------
         * Either "YYYY/MM/DD" or "DD/MM/YYYY"
         *------------------------------------------------------------*/
        if (strlen(papszTok[0]) == 4)

⌨️ 快捷键说明

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