?? dbfopen.c
字號(hào):
/****************************************************************************** * $Id: dbfopen.c,v 1.70 2006/06/17 17:47:05 fwarmerdam Exp $ * * Project: Shapelib * Purpose: Implementation of .dbf access API documented in dbf_api.html. * Author: Frank Warmerdam, warmerdam@pobox.com * ****************************************************************************** * Copyright (c) 1999, Frank Warmerdam * * This software is available under the following "MIT Style" license, * or at the option of the licensee under the LGPL (see LICENSE.LGPL). This * option is discussed in more detail in shapelib.html. * * -- * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************** * * $Log: dbfopen.c,v $ * Revision 1.70 2006/06/17 17:47:05 fwarmerdam * use calloc() for dbfinfo in DBFCreate * * Revision 1.69 2006/06/17 15:34:32 fwarmerdam * disallow creating fields wider than 255 * * Revision 1.68 2006/06/17 15:12:40 fwarmerdam * Fixed C++ style comments. * * Revision 1.67 2006/06/17 00:24:53 fwarmerdam * Don't treat non-zero decimals values as high order byte for length * for strings. It causes serious corruption for some files. * http://bugzilla.remotesensing.org/show_bug.cgi?id=1202 * * Revision 1.66 2006/03/29 18:26:20 fwarmerdam * fixed bug with size of pachfieldtype in dbfcloneempty * * Revision 1.65 2006/02/15 01:14:30 fwarmerdam * added DBFAddNativeFieldType * * Revision 1.64 2006/02/09 00:29:04 fwarmerdam * Changed to put spaces into string fields that are NULL as * per http://bugzilla.maptools.org/show_bug.cgi?id=316. * * Revision 1.63 2006/01/25 15:35:43 fwarmerdam * check success on DBFFlushRecord * * Revision 1.62 2006/01/10 16:28:03 fwarmerdam * Fixed typo in CPLError. * * Revision 1.61 2006/01/10 16:26:29 fwarmerdam * Push loading record buffer into DBFLoadRecord. * Implement CPL error reporting if USE_CPL defined. * * Revision 1.60 2006/01/05 01:27:27 fwarmerdam * added dbf deletion mark/fetch * * Revision 1.59 2005/03/14 15:20:28 fwarmerdam * Fixed last change. * * Revision 1.58 2005/03/14 15:18:54 fwarmerdam * Treat very wide fields with no decimals as double. This is * more than 32bit integer fields. * * Revision 1.57 2005/02/10 20:16:54 fwarmerdam * Make the pszStringField buffer for DBFReadAttribute() static char [256] * as per bug 306. * * Revision 1.56 2005/02/10 20:07:56 fwarmerdam * Fixed bug 305 in DBFCloneEmpty() - header length problem. * * Revision 1.55 2004/09/26 20:23:46 fwarmerdam * avoid warnings with rcsid and signed/unsigned stuff * * Revision 1.54 2004/09/15 16:26:10 fwarmerdam * Treat all blank numeric fields as null too. */#include "shapefil.h"#include <math.h>#include <stdlib.h>#include <ctype.h>#include <string.h>SHP_CVSID("$Id: dbfopen.c,v 1.70 2006/06/17 17:47:05 fwarmerdam Exp $")#ifndef FALSE# define FALSE 0# define TRUE 1#endif/************************************************************************//* SfRealloc() *//* *//* A realloc cover function that will access a NULL pointer as *//* a valid input. *//************************************************************************/static void * SfRealloc( void * pMem, int nNewSize ){ if( pMem == NULL ) return( (void *) malloc(nNewSize) ); else return( (void *) realloc(pMem,nNewSize) );}/************************************************************************//* DBFWriteHeader() *//* *//* This is called to write out the file header, and field *//* descriptions before writing any actual data records. This *//* also computes all the DBFDataSet field offset/size/decimals *//* and so forth values. *//************************************************************************/static void DBFWriteHeader(DBFHandle psDBF){ unsigned char abyHeader[XBASE_FLDHDR_SZ]; int i; if( !psDBF->bNoHeader ) return; psDBF->bNoHeader = FALSE;/* -------------------------------------------------------------------- *//* Initialize the file header information. *//* -------------------------------------------------------------------- */ for( i = 0; i < XBASE_FLDHDR_SZ; i++ ) abyHeader[i] = 0; abyHeader[0] = 0x03; /* memo field? - just copying */ /* write out a dummy date */ abyHeader[1] = 95; /* YY */ abyHeader[2] = 7; /* MM */ abyHeader[3] = 26; /* DD */ /* record count preset at zero */ abyHeader[8] = (unsigned char) (psDBF->nHeaderLength % 256); abyHeader[9] = (unsigned char) (psDBF->nHeaderLength / 256); abyHeader[10] = (unsigned char) (psDBF->nRecordLength % 256); abyHeader[11] = (unsigned char) (psDBF->nRecordLength / 256);/* -------------------------------------------------------------------- *//* Write the initial 32 byte file header, and all the field *//* descriptions. *//* -------------------------------------------------------------------- */ fseek( psDBF->fp, 0, 0 ); fwrite( abyHeader, XBASE_FLDHDR_SZ, 1, psDBF->fp ); fwrite( psDBF->pszHeader, XBASE_FLDHDR_SZ, psDBF->nFields, psDBF->fp );/* -------------------------------------------------------------------- *//* Write out the newline character if there is room for it. *//* -------------------------------------------------------------------- */ if( psDBF->nHeaderLength > 32*psDBF->nFields + 32 ) { char cNewline; cNewline = 0x0d; fwrite( &cNewline, 1, 1, psDBF->fp ); }}/************************************************************************//* DBFFlushRecord() *//* *//* Write out the current record if there is one. *//************************************************************************/static int DBFFlushRecord( DBFHandle psDBF ){ int nRecordOffset; if( psDBF->bCurrentRecordModified && psDBF->nCurrentRecord > -1 ) { psDBF->bCurrentRecordModified = FALSE; nRecordOffset = psDBF->nRecordLength * psDBF->nCurrentRecord + psDBF->nHeaderLength; if( fseek( psDBF->fp, nRecordOffset, 0 ) != 0 || fwrite( psDBF->pszCurrentRecord, psDBF->nRecordLength, 1, psDBF->fp ) != 1 ) {#ifdef USE_CPL CPLError( CE_Failure, CPLE_FileIO, "Failure writing DBF record %d.", psDBF->nCurrentRecord );#else fprintf( stderr, "Failure writing DBF record %d.", psDBF->nCurrentRecord );#endif return FALSE; } } return TRUE;}/************************************************************************//* DBFLoadRecord() *//************************************************************************/static int DBFLoadRecord( DBFHandle psDBF, int iRecord ){ if( psDBF->nCurrentRecord != iRecord ) { int nRecordOffset; if( !DBFFlushRecord( psDBF ) ) return FALSE; nRecordOffset = psDBF->nRecordLength * iRecord + psDBF->nHeaderLength; if( fseek( psDBF->fp, nRecordOffset, 0 ) != 0 ) {#ifdef USE_CPL CPLError( CE_Failure, CPLE_FileIO, "fseek(%d) failed on DBF file.\n", nRecordOffset );#else fprintf( stderr, "fseek(%d) failed on DBF file.\n", nRecordOffset );#endif return FALSE; } if( fread( psDBF->pszCurrentRecord, psDBF->nRecordLength, 1, psDBF->fp ) != 1 ) {#ifdef USE_CPL CPLError( CE_Failure, CPLE_FileIO, "fread(%d) failed on DBF file.\n", psDBF->nRecordLength );#else fprintf( stderr, "fread(%d) failed on DBF file.\n", psDBF->nRecordLength );#endif return FALSE; } psDBF->nCurrentRecord = iRecord; } return TRUE;}/************************************************************************//* DBFUpdateHeader() *//************************************************************************/void SHPAPI_CALLDBFUpdateHeader( DBFHandle psDBF ){ unsigned char abyFileHeader[32]; if( psDBF->bNoHeader ) DBFWriteHeader( psDBF ); DBFFlushRecord( psDBF ); fseek( psDBF->fp, 0, 0 ); fread( abyFileHeader, 32, 1, psDBF->fp ); abyFileHeader[4] = (unsigned char) (psDBF->nRecords % 256); abyFileHeader[5] = (unsigned char) ((psDBF->nRecords/256) % 256); abyFileHeader[6] = (unsigned char) ((psDBF->nRecords/(256*256)) % 256); abyFileHeader[7] = (unsigned char) ((psDBF->nRecords/(256*256*256)) % 256); fseek( psDBF->fp, 0, 0 ); fwrite( abyFileHeader, 32, 1, psDBF->fp ); fflush( psDBF->fp );}/************************************************************************//* DBFOpen() *//* *//* Open a .dbf file. *//************************************************************************/ DBFHandle SHPAPI_CALLDBFOpen( const char * pszFilename, const char * pszAccess ){ DBFHandle psDBF; unsigned char *pabyBuf; int nFields, nHeadLen, iField, i; char *pszBasename, *pszFullname;/* -------------------------------------------------------------------- *//* We only allow the access strings "rb" and "r+". *//* -------------------------------------------------------------------- */ if( strcmp(pszAccess,"r") != 0 && strcmp(pszAccess,"r+") != 0 && strcmp(pszAccess,"rb") != 0 && strcmp(pszAccess,"rb+") != 0 && strcmp(pszAccess,"r+b") != 0 ) return( NULL ); if( strcmp(pszAccess,"r") == 0 ) pszAccess = "rb"; if( strcmp(pszAccess,"r+") == 0 ) pszAccess = "rb+";/* -------------------------------------------------------------------- *//* Compute the base (layer) name. If there is any extension *//* on the passed in filename we will strip it off. *//* -------------------------------------------------------------------- */ pszBasename = (char *) malloc(strlen(pszFilename)+5); strcpy( pszBasename, pszFilename ); for( i = strlen(pszBasename)-1; i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/' && pszBasename[i] != '\\'; i-- ) {} if( pszBasename[i] == '.' ) pszBasename[i] = '\0'; pszFullname = (char *) malloc(strlen(pszBasename) + 5); sprintf( pszFullname, "%s.dbf", pszBasename ); psDBF = (DBFHandle) calloc( 1, sizeof(DBFInfo) ); psDBF->fp = fopen( pszFullname, pszAccess ); if( psDBF->fp == NULL ) { sprintf( pszFullname, "%s.DBF", pszBasename ); psDBF->fp = fopen(pszFullname, pszAccess ); } free( pszBasename ); free( pszFullname ); if( psDBF->fp == NULL ) { free( psDBF ); return( NULL ); } psDBF->bNoHeader = FALSE; psDBF->nCurrentRecord = -1; psDBF->bCurrentRecordModified = FALSE;/* -------------------------------------------------------------------- *//* Read Table Header info *//* -------------------------------------------------------------------- */ pabyBuf = (unsigned char *) malloc(500); if( fread( pabyBuf, 32, 1, psDBF->fp ) != 1 ) { fclose( psDBF->fp ); free( pabyBuf ); free( psDBF ); return NULL; } psDBF->nRecords = pabyBuf[4] + pabyBuf[5]*256 + pabyBuf[6]*256*256 + pabyBuf[7]*256*256*256; psDBF->nHeaderLength = nHeadLen = pabyBuf[8] + pabyBuf[9]*256; psDBF->nRecordLength = pabyBuf[10] + pabyBuf[11]*256;
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -