📄 cpl_csv.cpp
字号:
/************************************************************************/
char **CSVScanFile( const char * pszFilename, int iKeyField,
const char * pszValue, CSVCompareCriteria eCriteria )
{
CSVTable *psTable;
/* -------------------------------------------------------------------- */
/* Get access to the table. */
/* -------------------------------------------------------------------- */
CPLAssert( pszFilename != NULL );
if( iKeyField < 0 )
return NULL;
psTable = CSVAccess( pszFilename );
if( psTable == NULL )
return NULL;
CSVIngest( pszFilename );
/* -------------------------------------------------------------------- */
/* Does the current record match the criteria? If so, just */
/* return it again. */
/* -------------------------------------------------------------------- */
if( iKeyField >= 0
&& iKeyField < CSLCount(psTable->papszRecFields)
&& CSVCompare(pszValue,psTable->papszRecFields[iKeyField],eCriteria) )
{
return psTable->papszRecFields;
}
/* -------------------------------------------------------------------- */
/* Scan the file from the beginning, replacing the ``current */
/* record'' in our structure with the one that is found. */
/* -------------------------------------------------------------------- */
psTable->iLastLine = -1;
CSLDestroy( psTable->papszRecFields );
if( psTable->pszRawData != NULL )
psTable->papszRecFields =
CSVScanLinesIngested( psTable, iKeyField, pszValue, eCriteria );
else
{
VSIRewind( psTable->fp );
CPLReadLine( psTable->fp ); /* throw away the header line */
psTable->papszRecFields =
CSVScanLines( psTable->fp, iKeyField, pszValue, eCriteria );
}
return( psTable->papszRecFields );
}
/************************************************************************/
/* CPLGetFieldId() */
/* */
/* Read the first record of a CSV file (rewinding to be sure), */
/* and find the field with the indicated name. Returns -1 if */
/* it fails to find the field name. Comparison is case */
/* insensitive, but otherwise exact. After this function has */
/* been called the file pointer will be positioned just after */
/* the first record. */
/************************************************************************/
int CSVGetFieldId( FILE * fp, const char * pszFieldName )
{
char **papszFields;
int i;
CPLAssert( fp != NULL && pszFieldName != NULL );
VSIRewind( fp );
papszFields = CSVReadParseLine( fp );
for( i = 0; papszFields != NULL && papszFields[i] != NULL; i++ )
{
if( EQUAL(papszFields[i],pszFieldName) )
{
CSLDestroy( papszFields );
return i;
}
}
CSLDestroy( papszFields );
return -1;
}
/************************************************************************/
/* CSVGetFileFieldId() */
/* */
/* Same as CPLGetFieldId(), except that we get the file based */
/* on filename, rather than having an existing handle. */
/************************************************************************/
int CSVGetFileFieldId( const char * pszFilename, const char * pszFieldName )
{
CSVTable *psTable;
int i;
/* -------------------------------------------------------------------- */
/* Get access to the table. */
/* -------------------------------------------------------------------- */
CPLAssert( pszFilename != NULL );
psTable = CSVAccess( pszFilename );
if( psTable == NULL )
return -1;
/* -------------------------------------------------------------------- */
/* Find the requested field. */
/* -------------------------------------------------------------------- */
for( i = 0;
psTable->papszFieldNames != NULL
&& psTable->papszFieldNames[i] != NULL;
i++ )
{
if( EQUAL(psTable->papszFieldNames[i],pszFieldName) )
{
return i;
}
}
return -1;
}
/************************************************************************/
/* CSVScanFileByName() */
/* */
/* Same as CSVScanFile(), but using a field name instead of a */
/* field number. */
/************************************************************************/
char **CSVScanFileByName( const char * pszFilename,
const char * pszKeyFieldName,
const char * pszValue, CSVCompareCriteria eCriteria )
{
int iKeyField;
iKeyField = CSVGetFileFieldId( pszFilename, pszKeyFieldName );
if( iKeyField == -1 )
return NULL;
return( CSVScanFile( pszFilename, iKeyField, pszValue, eCriteria ) );
}
/************************************************************************/
/* CSVGetField() */
/* */
/* The all-in-one function to fetch a particular field value */
/* from a CSV file. Note this function will return an empty */
/* string, rather than NULL if it fails to find the desired */
/* value for some reason. The caller can't establish that the */
/* fetch failed. */
/************************************************************************/
const char *CSVGetField( const char * pszFilename,
const char * pszKeyFieldName,
const char * pszKeyFieldValue,
CSVCompareCriteria eCriteria,
const char * pszTargetField )
{
CSVTable *psTable;
char **papszRecord;
int iTargetField;
/* -------------------------------------------------------------------- */
/* Find the table. */
/* -------------------------------------------------------------------- */
psTable = CSVAccess( pszFilename );
if( psTable == NULL )
return "";
/* -------------------------------------------------------------------- */
/* Find the correct record. */
/* -------------------------------------------------------------------- */
papszRecord = CSVScanFileByName( pszFilename, pszKeyFieldName,
pszKeyFieldValue, eCriteria );
if( papszRecord == NULL )
return "";
/* -------------------------------------------------------------------- */
/* Figure out which field we want out of this. */
/* -------------------------------------------------------------------- */
iTargetField = CSVGetFileFieldId( pszFilename, pszTargetField );
if( iTargetField < 0 )
return "";
if( iTargetField >= CSLCount( papszRecord ) )
return "";
return( papszRecord[iTargetField] );
}
/************************************************************************/
/* GDALDefaultCSVFilename() */
/************************************************************************/
const char * GDALDefaultCSVFilename( const char *pszBasename )
{
static CPL_THREADLOCAL char szPath[512];
FILE *fp = NULL;
const char *pszResult;
static CPL_THREADLOCAL int bCSVFinderInitialized = FALSE;
pszResult = CPLFindFile( "epsg_csv", pszBasename );
if( pszResult != NULL )
return pszResult;
if( !bCSVFinderInitialized )
{
bCSVFinderInitialized = TRUE;
if( CPLGetConfigOption("GEOTIFF_CSV",NULL) != NULL )
CPLPushFinderLocation( CPLGetConfigOption("GEOTIFF_CSV",NULL));
if( CPLGetConfigOption("GDAL_DATA",NULL) != NULL )
CPLPushFinderLocation( CPLGetConfigOption("GDAL_DATA",NULL) );
pszResult = CPLFindFile( "epsg_csv", pszBasename );
if( pszResult != NULL )
return pszResult;
}
if( (fp = fopen( "csv/horiz_cs.csv", "rt" )) != NULL )
{
sprintf( szPath, "csv/%s", pszBasename );
}
else
{
#ifdef GDAL_PREFIX
#ifdef MACOSX_FRAMEWORK
sprintf( szPath, GDAL_PREFIX "/Resources/epsg_csv/%s", pszBasename );
#else
sprintf( szPath, GDAL_PREFIX "/share/epsg_csv/%s", pszBasename );
#endif
#else
sprintf( szPath, "/usr/local/share/epsg_csv/%s", pszBasename );
#endif
if( (fp = fopen( szPath, "rt" )) == NULL )
strcpy( szPath, pszBasename );
}
if( fp != NULL )
fclose( fp );
return( szPath );
}
/************************************************************************/
/* CSVFilename() */
/* */
/* Return the full path to a particular CSV file. This will */
/* eventually be something the application can override. */
/************************************************************************/
static const char *(*pfnCSVFilenameHook)(const char *) = NULL;
const char * CSVFilename( const char *pszBasename )
{
if( pfnCSVFilenameHook == NULL )
return GDALDefaultCSVFilename( pszBasename );
else
return( pfnCSVFilenameHook( pszBasename ) );
}
/************************************************************************/
/* SetCSVFilenameHook() */
/* */
/* Applications can use this to set a function that will */
/* massage CSV filenames. */
/************************************************************************/
/**
* Override CSV file search method.
*
* @param CSVFileOverride The pointer to a function which will return the
* full path for a given filename.
*
This function allows an application to override how the GTIFGetDefn() and related function find the CSV (Comma Separated
Value) values required. The pfnHook argument should be a pointer to a function that will take in a CSV filename and return a
full path to the file. The returned string should be to an internal static buffer so that the caller doesn't have to free the result.
<b>Example:</b><br>
The listgeo utility uses the following override function if the user
specified a CSV file directory with the -t commandline switch (argument
put into CSVDirName). <p>
<pre>
...
SetCSVFilenameHook( CSVFileOverride );
...
static const char *CSVFileOverride( const char * pszInput )
{
static char szPath[1024];
#ifdef WIN32
sprintf( szPath, "%s\\%s", CSVDirName, pszInput );
#else
sprintf( szPath, "%s/%s", CSVDirName, pszInput );
#endif
return( szPath );
}
</pre>
*/
CPL_C_START
void SetCSVFilenameHook( const char *(*pfnNewHook)( const char * ) )
{
pfnCSVFilenameHook = pfnNewHook;
}
CPL_C_END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -