📄 cpl_csv.cpp
字号:
int nFileLen, i, nMaxLineCount, iLine = 0;
char *pszThisLine;
if( psTable->pszRawData != NULL )
return;
/* -------------------------------------------------------------------- */
/* Ingest whole file. */
/* -------------------------------------------------------------------- */
VSIFSeek( psTable->fp, 0, SEEK_END );
nFileLen = VSIFTell( psTable->fp );
VSIRewind( psTable->fp );
psTable->pszRawData = (char *) CPLMalloc(nFileLen+1);
if( (int) VSIFRead( psTable->pszRawData, 1, nFileLen, psTable->fp )
!= nFileLen )
{
CPLFree( psTable->pszRawData );
psTable->pszRawData = NULL;
CPLError( CE_Failure, CPLE_FileIO, "Read of file %s failed.",
psTable->pszFilename );
return;
}
psTable->pszRawData[nFileLen] = '\0';
/* -------------------------------------------------------------------- */
/* Get count of newlines so we can allocate line array. */
/* -------------------------------------------------------------------- */
nMaxLineCount = 0;
for( i = 0; i < nFileLen; i++ )
{
if( psTable->pszRawData[i] == 10 )
nMaxLineCount++;
}
psTable->papszLines = (char **) CPLCalloc(sizeof(char*),nMaxLineCount);
/* -------------------------------------------------------------------- */
/* Build a list of record pointers into the raw data buffer */
/* based on line terminators. Zero terminate the line */
/* strings. */
/* -------------------------------------------------------------------- */
/* skip header line */
pszThisLine = CSVFindNextLine( psTable->pszRawData );
while( pszThisLine != NULL && iLine < nMaxLineCount )
{
psTable->papszLines[iLine++] = pszThisLine;
pszThisLine = CSVFindNextLine( pszThisLine );
}
psTable->nLineCount = iLine;
/* -------------------------------------------------------------------- */
/* Allocate and populate index array. Ensure they are in */
/* ascending order so that binary searches can be done on the */
/* array. */
/* -------------------------------------------------------------------- */
psTable->panLineIndex = (int *) CPLMalloc(sizeof(int)*psTable->nLineCount);
for( i = 0; i < psTable->nLineCount; i++ )
{
psTable->panLineIndex[i] = atoi(psTable->papszLines[i]);
if( i > 0 && psTable->panLineIndex[i] < psTable->panLineIndex[i-1] )
{
CPLFree( psTable->panLineIndex );
psTable->panLineIndex = NULL;
break;
}
}
psTable->iLastLine = -1;
/* -------------------------------------------------------------------- */
/* We should never need the file handle against, so close it. */
/* -------------------------------------------------------------------- */
VSIFClose( psTable->fp );
psTable->fp = NULL;
}
/************************************************************************/
/* CSVReadParseLine() */
/* */
/* Read one line, and return split into fields. The return */
/* result is a stringlist, in the sense of the CSL functions. */
/************************************************************************/
char **CSVReadParseLine( FILE * fp )
{
const char *pszLine;
char *pszWorkLine;
char **papszReturn;
CPLAssert( fp != NULL );
if( fp == NULL )
return( NULL );
pszLine = CPLReadLine( fp );
if( pszLine == NULL )
return( NULL );
/* -------------------------------------------------------------------- */
/* If there are no quotes, then this is the simple case. */
/* Parse, and return tokens. */
/* -------------------------------------------------------------------- */
if( strchr(pszLine,'\"') == NULL )
return CSVSplitLine( pszLine );
/* -------------------------------------------------------------------- */
/* We must now count the quotes in our working string, and as */
/* long as it is odd, keep adding new lines. */
/* -------------------------------------------------------------------- */
pszWorkLine = CPLStrdup( pszLine );
while( TRUE )
{
int i, nCount = 0;
for( i = 0; pszWorkLine[i] != '\0'; i++ )
{
if( pszWorkLine[i] == '\"'
&& (i == 0 || pszWorkLine[i-1] != '\\') )
nCount++;
}
if( nCount % 2 == 0 )
break;
pszLine = CPLReadLine( fp );
if( pszLine == NULL )
break;
pszWorkLine = (char *)
CPLRealloc(pszWorkLine,
strlen(pszWorkLine) + strlen(pszLine) + 2);
strcat( pszWorkLine, "\n" ); // This gets lost in CPLReadLine().
strcat( pszWorkLine, pszLine );
}
papszReturn = CSVSplitLine( pszWorkLine );
CPLFree( pszWorkLine );
return papszReturn;
}
/************************************************************************/
/* CSVCompare() */
/* */
/* Compare a field to a search value using a particular */
/* criteria. */
/************************************************************************/
static int CSVCompare( const char * pszFieldValue, const char * pszTarget,
CSVCompareCriteria eCriteria )
{
if( eCriteria == CC_ExactString )
{
return( strcmp( pszFieldValue, pszTarget ) == 0 );
}
else if( eCriteria == CC_ApproxString )
{
return( EQUAL( pszFieldValue, pszTarget ) );
}
else if( eCriteria == CC_Integer )
{
return( atoi(pszFieldValue) == atoi(pszTarget) );
}
return FALSE;
}
/************************************************************************/
/* CSVScanLines() */
/* */
/* Read the file scanline for lines where the key field equals */
/* the indicated value with the suggested comparison criteria. */
/* Return the first matching line split into fields. */
/************************************************************************/
char **CSVScanLines( FILE *fp, int iKeyField, const char * pszValue,
CSVCompareCriteria eCriteria )
{
char **papszFields = NULL;
int bSelected = FALSE, nTestValue;
CPLAssert( pszValue != NULL );
CPLAssert( iKeyField >= 0 );
CPLAssert( fp != NULL );
nTestValue = atoi(pszValue);
while( !bSelected ) {
papszFields = CSVReadParseLine( fp );
if( papszFields == NULL )
return( NULL );
if( CSLCount( papszFields ) < iKeyField+1 )
{
/* not selected */
}
else if( eCriteria == CC_Integer
&& atoi(papszFields[iKeyField]) == nTestValue )
{
bSelected = TRUE;
}
else
{
bSelected = CSVCompare( papszFields[iKeyField], pszValue,
eCriteria );
}
if( !bSelected )
{
CSLDestroy( papszFields );
papszFields = NULL;
}
}
return( papszFields );
}
/************************************************************************/
/* CSVScanLinesIndexed() */
/* */
/* Read the file scanline for lines where the key field equals */
/* the indicated value with the suggested comparison criteria. */
/* Return the first matching line split into fields. */
/************************************************************************/
static char **
CSVScanLinesIndexed( CSVTable *psTable, int nKeyValue )
{
int iTop, iBottom, iMiddle, iResult = -1;
CPLAssert( psTable->panLineIndex != NULL );
/* -------------------------------------------------------------------- */
/* Find target record with binary search. */
/* -------------------------------------------------------------------- */
iTop = psTable->nLineCount-1;
iBottom = 0;
while( iTop >= iBottom )
{
iMiddle = (iTop + iBottom) / 2;
if( psTable->panLineIndex[iMiddle] > nKeyValue )
iTop = iMiddle - 1;
else if( psTable->panLineIndex[iMiddle] < nKeyValue )
iBottom = iMiddle + 1;
else
{
iResult = iMiddle;
break;
}
}
if( iResult == -1 )
return NULL;
/* -------------------------------------------------------------------- */
/* Parse target line, and update iLastLine indicator. */
/* -------------------------------------------------------------------- */
psTable->iLastLine = iResult;
return CSVSplitLine( psTable->papszLines[iResult] );
}
/************************************************************************/
/* CSVScanLinesIngested() */
/* */
/* Read the file scanline for lines where the key field equals */
/* the indicated value with the suggested comparison criteria. */
/* Return the first matching line split into fields. */
/************************************************************************/
static char **
CSVScanLinesIngested( CSVTable *psTable, int iKeyField, const char * pszValue,
CSVCompareCriteria eCriteria )
{
char **papszFields = NULL;
int bSelected = FALSE, nTestValue;
CPLAssert( pszValue != NULL );
CPLAssert( iKeyField >= 0 );
nTestValue = atoi(pszValue);
/* -------------------------------------------------------------------- */
/* Short cut for indexed files. */
/* -------------------------------------------------------------------- */
if( iKeyField == 0 && eCriteria == CC_Integer
&& psTable->panLineIndex != NULL )
return CSVScanLinesIndexed( psTable, nTestValue );
/* -------------------------------------------------------------------- */
/* Scan from in-core lines. */
/* -------------------------------------------------------------------- */
while( !bSelected && psTable->iLastLine+1 < psTable->nLineCount ) {
psTable->iLastLine++;
papszFields = CSVSplitLine( psTable->papszLines[psTable->iLastLine] );
if( CSLCount( papszFields ) < iKeyField+1 )
{
/* not selected */
}
else if( eCriteria == CC_Integer
&& atoi(papszFields[iKeyField]) == nTestValue )
{
bSelected = TRUE;
}
else
{
bSelected = CSVCompare( papszFields[iKeyField], pszValue,
eCriteria );
}
if( !bSelected )
{
CSLDestroy( papszFields );
papszFields = NULL;
}
}
return( papszFields );
}
/************************************************************************/
/* CSVScanFile() */
/* */
/* Scan a whole file using criteria similar to above, but also */
/* taking care of file opening and closing. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -