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

📄 cpl_csv.cpp

📁 用于读取TAB、MIF、SHP文件的类
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/************************************************************************//*                          CSVFindNextLine()                           *//*                                                                      *//*      Find the start of the next line, while at the same time zero    *//*      terminating this line.  Take into account that there may be     *//*      newline indicators within quoted strings, and that quotes       *//*      can be escaped with a backslash.                                *//************************************************************************/static char *CSVFindNextLine( char *pszThisLine ){    int  nQuoteCount = 0, i;    for( i = 0; pszThisLine[i] != '\0'; i++ )    {        if( pszThisLine[i] == '\"'            && (i == 0 || pszThisLine[i-1] != '\\') )            nQuoteCount++;        if( (pszThisLine[i] == 10 || pszThisLine[i] == 13)            && (nQuoteCount % 2) == 0 )            break;    }    while( pszThisLine[i] == 10 || pszThisLine[i] == 13 )        pszThisLine[i++] = '\0';    if( pszThisLine[i] == '\0' )        return NULL;    else        return pszThisLine + i;}/************************************************************************//*                             CSVIngest()                              *//*                                                                      *//*      Load entire file into memory and setup index if possible.       *//************************************************************************/static void CSVIngest( const char *pszFilename ){    CSVTable *psTable = CSVAccess( pszFilename );    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;

⌨️ 快捷键说明

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