📄 mitab_datfile.cpp
字号:
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 + -