?? avc_binwr.c
字號:
* will be reused and overwritten. * * Note: there could be a problem if 2 processes try to add an entry * at the exact same time... does Arc/Info do any locking on that file??? * * Returns an integer value corresponding to the new table index (ARC####) * or -1 if something failed. **********************************************************************//* Prototype for _AVCBinReadNextArcDir() from avc_bin.c */int _AVCBinReadNextArcDir(AVCRawBinFile *psFile, AVCTableDef *psArcDir);int _AVCBinWriteCreateArcDirEntry(const char *pszArcDirFile, AVCTableDef *psTableDef, AVCDBCSInfo *psDBCSInfo){ int iEntry, numDirEntries=0, nTableIndex = 0; VSIStatBuf sStatBuf; AVCRawBinFile *hRawBinFile; GBool bFound; AVCTableDef sEntry; /*----------------------------------------------------------------- * Open and Scan the ARC.DIR to establish the table index (ARC####) *----------------------------------------------------------------*/#ifdef _WIN32 /*----------------------------------------------------------------- * Note, DM, 20010507 - We used to use VSIFStat() to establish the * size of arc.dir, but when working on a WinNT4 networked drive, the * stat() information was not always right, and we sometimes ended * up overwriting arc.dir entries. The solution: open and scan arc.dir * until EOF to establish its size. * That trick also seems to fix another network buffer problem: when * writing a coverage in a new empty dir (with no info dir yet), we * would get an error in fwrite() while writing the 3rd arc.dir * entry of the coverage. That second problem could also have been * fixed by forcing a VSIFSeek() before the first fwrite()... we've * added it below. *----------------------------------------------------------------*/ FILE *fp; if ((fp = VSIFOpen(pszArcDirFile, "r")) != NULL) { char buf[380]; while (!VSIFEof(fp)) { if (VSIFRead(buf, 380, 1, fp) == 1) numDirEntries++; } VSIFClose(fp); hRawBinFile = AVCRawBinOpen(pszArcDirFile, "r+", AVC_COVER_BYTE_ORDER(AVCCoverV7), psDBCSInfo); } else #endif /* On Unix we can still use fstat() */ if ( VSIStat(pszArcDirFile, &sStatBuf) != -1 ) { numDirEntries = sStatBuf.st_size/380; hRawBinFile = AVCRawBinOpen(pszArcDirFile, "r+", AVC_COVER_BYTE_ORDER(AVCCoverV7), psDBCSInfo); } else { numDirEntries = 0; hRawBinFile = AVCRawBinOpen(pszArcDirFile, "w", AVC_COVER_BYTE_ORDER(AVCCoverV7), psDBCSInfo); } if (hRawBinFile == NULL) { /* Failed to open file... just return -1 since an error message * has already been issued by AVCRawBinOpen() */ return -1; } /* Init nTableIndex at -1 so that first table created should have * index 0 */ nTableIndex = -1; iEntry = 0; bFound = FALSE; while(!bFound && iEntry<numDirEntries && _AVCBinReadNextArcDir(hRawBinFile, &sEntry) == 0) { nTableIndex = atoi(sEntry.szInfoFile+3); if (EQUALN(psTableDef->szTableName, sEntry.szTableName, strlen(psTableDef->szTableName))) { bFound = TRUE; break; } iEntry++; } /*----------------------------------------------------------------- * Reposition the file pointer and write the entry. * * We use VSIFSeek() directly since the AVCRawBin*() functions do * not support random access yet... it is OK to do so here since the * ARC.DIR does not have a header and we will close it right away. *----------------------------------------------------------------*/ if (bFound) VSIFSeek(hRawBinFile->fp, iEntry*380, SEEK_SET); else { /* Not found... Use the next logical table index */ nTableIndex++; /* We're already at EOF so we shouldn't need to fseek here, but * ANSI-C requires that a file positioning function be called * between read and writes... this had never been a problem before * on any system except with NT4 network drives. */ VSIFSeek(hRawBinFile->fp, numDirEntries*380, SEEK_SET); } sprintf(psTableDef->szInfoFile, "ARC%4.4d", nTableIndex); _AVCBinWriteArcDir(hRawBinFile, psTableDef); AVCRawBinClose(hRawBinFile); return nTableIndex;}/********************************************************************** * AVCBinWriteCreateTable() * * Open an INFO table for writing: * * - Add an entry for the new table in the info/arc.dir * - Write the attributes definitions to the info/arc####.nit * - Create the data file, ready to write data records to it * - If necessary, set the arc####.dat to point to the location of * the data file. * * pszInfoPath is the info directory path, terminated by a '/' or a '\\' * It is assumed that this 'info' directory already exists and is writable. * * psTableDef should contain a valid table definition for this coverage. * This function will create and maintain its own copy of the structure. * * The name of the file to create and its location will be based on the * table name and the external ("XX") flag values in the psTableDef * structure, so you have to make sure that these values are valid. * * If a table with the same name is already present in the arc.dir, then * the same arc.dir entry will be used and overwritten. This happens * when a coverage directory is deleted by hand. The behavior implemented * here correspond to Arc/Info's behavior. * * For internal tables, the data file goes directly in the info directory, so * there is not much to worry about. * * For external tables, the table name is composed of 3 parts: * * <COVERNAME>.<EXT><SUBCLASSNAME> * * - <COVERNAME>: * The first part of the table name (before the '.') is the * name of the coverage to which the table belongs, and the data file * will be created in this coverage's directory... so it is assumed that * the directory "../<covername>" already exists and is writable. * - <EXT>: * The coverage name is followed by a 3 chars extension that will be * used to build the name of the external table to create. * - <SUBCLASSNAME>: * For some table types, the extension is followed by a subclass name. * * When <SUBCLASSNAME> is present, then the data file name will be: * "../<covername>/<subclassname>.<ext>" * * e.g. The table named "TEST.PATCOUNTY" would be stored in the file * "../test/county.pat" (this path is realtive to the info directory) * * When the <SUBCLASSNAME> is not present, then the name of the data file * will be the "../<covername>/<ext>.adf" * * e.g. The table named "TEST.PAT" would be stored in the file * "../test/pat.adf" * * Of course, it would be too easy if there were no exceptions to these * rules! Single precision ".TIC" and ".BND" follow the above rules and * will be named "tic.adf" and "bnd.adf" but in double precision coverages, * they will be named "dbltic.adf" and "dblbnd.adf". * * Returns a valid AVCBinFile handle, or NULL if the table could * not be created. * * AVCBinClose() will eventually have to be called to release the * resources used by the AVCBinFile structure. **********************************************************************/AVCBinFile *AVCBinWriteCreateTable(const char *pszInfoPath, const char *pszCoverName, AVCTableDef *psSrcTableDef, AVCCoverType eCoverType, int nPrecision, AVCDBCSInfo *psDBCSInfo){ AVCBinFile *psFile; AVCRawBinFile *hRawBinFile; AVCTableDef *psTableDef = NULL; char *pszFname = NULL, szInfoFile[8]=""; int i, nTableIndex = 0; if (eCoverType == AVCCoverPC || eCoverType == AVCCoverPC2) return _AVCBinWriteCreateDBFTable(pszInfoPath, pszCoverName, psSrcTableDef, eCoverType, nPrecision, psDBCSInfo); /*----------------------------------------------------------------- * Make sure precision value is valid (AVC_DEFAULT_PREC is NOT valid) *----------------------------------------------------------------*/ if (nPrecision!=AVC_SINGLE_PREC && nPrecision!=AVC_DOUBLE_PREC) { CPLError(CE_Failure, CPLE_IllegalArg, "AVCBinWriteCreateTable(): Invalid precision parameter " "(value must be AVC_SINGLE_PREC or AVC_DOUBLE_PREC)"); return NULL; } /* Alloc a buffer big enough for the longest possible filename... */ pszFname = (char*)CPLMalloc((strlen(pszInfoPath)+81)*sizeof(char)); /*----------------------------------------------------------------- * Alloc and init the AVCBinFile struct. *----------------------------------------------------------------*/ psFile = (AVCBinFile*)CPLCalloc(1, sizeof(AVCBinFile)); psFile->eFileType = AVCFileTABLE; /* Precision is not important for tables */ psFile->nPrecision = nPrecision; psFile->eCoverType = eCoverType; psFile->hdr.psTableDef = psTableDef = _AVCDupTableDef(psSrcTableDef); /*----------------------------------------------------------------- * Add a record for this table in the "arc.dir" * Note: there could be a problem if 2 processes try to add an entry * at the exact same time... does Arc/Info do any locking on that file??? *----------------------------------------------------------------*/ sprintf(pszFname, "%sarc.dir", pszInfoPath); nTableIndex = _AVCBinWriteCreateArcDirEntry(pszFname, psTableDef, psDBCSInfo); if (nTableIndex < 0) { /* Failed to add arc.dir entry... just return NULL since an error * message has already been issued by _AVCBinWriteCreateArcDirEntry() */ _AVCDestroyTableDef(psTableDef); CPLFree(psFile); CPLFree(pszFname); return NULL; } sprintf(szInfoFile, "arc%4.4d", nTableIndex); /*----------------------------------------------------------------- * Create the "arc####.nit" with the attribute definitions. *----------------------------------------------------------------*/ sprintf(pszFname, "%s%s.nit", pszInfoPath, szInfoFile); hRawBinFile = AVCRawBinOpen(pszFname, "w", AVC_COVER_BYTE_ORDER(AVCCoverV7), psDBCSInfo); if (hRawBinFile == NULL) { /* Failed to open file... just return NULL since an error message * has already been issued by AVCRawBinOpen() */ _AVCDestroyTableDef(psTableDef); CPLFree(psFile); CPLFree(pszFname); return NULL; } for(i=0; i<psTableDef->numFields; i++) { _AVCBinWriteArcNit(hRawBinFile, &(psTableDef->pasFieldDef[i])); } AVCRawBinClose(hRawBinFile); hRawBinFile = NULL; /*----------------------------------------------------------------- * The location of the data file depends on the external flag. *----------------------------------------------------------------*/ if (EQUAL(psTableDef->szExternal, " ")) { /*------------------------------------------------------------- * Internal table: data goes directly in "arc####.dat" *------------------------------------------------------------*/ sprintf(pszFname, "%s%s.dat", pszInfoPath, szInfoFile); psFile->pszFilename = CPLStrdup(pszFname); } else { /*------------------------------------------------------------- * External table: data stored in the coverage directory, and * the path to the data file is written to "arc####.dat" *... start by extracting the info to build the data file name... *------------------------------------------------------------*/ char szCoverName[40]="", szExt[4]="", szSubclass[40]="", *pszPtr; int nLen; FILE *fpOut; nLen = strlen(psTableDef->szTableName); CPLAssert(nLen <= 32); if (nLen > 32) return NULL; pszPtr = psTableDef->szTableName; for(i=0; *pszPtr!='\0' && *pszPtr!='.' && *pszPtr!=' '; i++, pszPtr++) { szCoverName[i] = tolower(*pszPtr); } szCoverName[i] = '\0'; if (*pszPtr == '.') pszPtr++; for(i=0; i<3 && *pszPtr!='\0' && *pszPtr!=' '; i++, pszPtr++) { szExt[i] = tolower(*pszPtr); } szExt[i] = '\0'; for(i=0; *pszPtr!='\0' && *pszPtr!=' '; i++, pszPtr++) { szSubclass[i] = tolower(*pszPtr); } szSubclass[i] = '\0'; /*------------------------------------------------------------- * ... and build the data file name based on what we extracted *------------------------------------------------------------*/ if (strlen(szSubclass) == 0) { if (nPrecision == AVC_DOUBLE_PREC && (EQUAL(szExt, "TIC") || EQUAL(szExt, "BND")) ) { /* "../<covername>/dbl<ext>.adf" */ sprintf(psTableDef->szDataFile, "../%s/dbl%s.adf", szCoverName, szExt); } else { /* "../<covername>/<ext>.adf" */ sprintf(psTableDef->szDataFile, "../%s/%s.adf", szCoverName, szExt); }
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -