RFC 12:改进的文件管理

作者:弗兰克·温特丹

联系方式:warmerdam@pobox.com

状态:通过/实施

总结

一些使用GDAL的应用程序需要通过GUI提供文件管理操作。这包括删除、重命名、移动和打包数据集,这些数据集通常需要对多个相关文件执行操作。此RFC在GDALDataset上引入一个操作来标识所有数据集文件,以及移动或复制这些文件的操作。

获取文件列表()

在GDALDataset类中添加了以下新的虚方法,其中包含一个analygous C函数。

virtual char   **GDALDataset::GetFileList(void);

此方法旨在返回与此打开的数据集关联的文件列表。返回的是一个以空结尾的字符串列表,该列表归调用者所有,应使用csldestory()解除分配。

默认实现测试数据源的名称,看它是否是文件,如果是,则返回空列表。如果默认的概述管理器处于活动状态,并且具有概述,则这些概述也将包含在文件列表中。默认实现还检查world文件,但仅检查扩展名基于原始文件扩展名的文件(即.tfw或.tifw用于.tif),但不搜索.wld,因为这不是很具体。

GDALPamDataset::GetFileList()方法将把查找与数据集关联的.aux和.aux.xml文件的能力添加到核心默认行为中。

pfnRename()

下面的新函数被添加到GDALDriver类中。

CPLErr       (*pfnRename)( const char *pszNewName, const char *pszOldName );

此外,还向C API添加了相应的函数。

CPLErr        GDALRenameDataset( GDALDriverH hDriver, const char *pszNewName, const char *pszOldName );

注意,重命名是由驱动程序完成的,但是要操作的数据集应该 not 当时是开放的。如果不是空的,GDALRenameDataset()将调用pfnRename。

如果pfnRename为空,则将使用默认实现,该实现将打开数据集、获取文件列表、关闭数据集,然后尝试重命名所有文件(基于共享基名)。如果默认重命名操作无法在文件之间建立关系(即公共基名称或词干)以指示如何将文件组重命名为新模式,则该操作将失败。

可选地,可以传入空的hDriver参数,在这种情况下,将通过首先打开数据源来选择适当的驱动程序。

CPLMoveFile()

VSIRename()通常基于的POSIX rename()函数通常不允许在文件系统之间或不同类型的文件系统之间重命名文件(即/vsimem到C:/abc)。为了实现GDALRenameDataset(),使其在文件系统中高效工作,但仍在文件系统之间工作,将向gdal/port添加一个新操作。这是CPLMoveFile()函数,它将首先尝试VSIRename()。如果失败,它将使用CPLCopyFile()复制整个文件,然后使用VSIUnlink()删除旧文件。

int CPLMoveFile( const char *pszNewFilename, const char *pszOldFilename );

成功时返回值将为零,否则为errno样式值。

需要注意的是,在某些错误情况下,例如目标文件系统在复制过程中空间不足,可能会发生数据集的某些文件被重命名,而有些文件不会使内容处于不一致的状态。

pfnCopyFiles()

下面的新函数被添加到GDALDriver类中。

CPLErr       (*pfnCopyFiles)( const char *pszNewName, const char *pszOldName );

此外,还向C API添加了相应的函数。

CPLErr        GDALCopyDatasetFiles( GDALDriverH hDriver, const char *pszNewName, const char *pszOldName );

注意,复制是由驱动程序完成的。数据集可能已打开,但如果在更新模式下打开,则可能需要先执行刷新操作以将进程内状态与磁盘上的状态同步。如果非空,GDALCopyDatasetFiles()将调用pfnCopyFiles。

如果pfnCopy为空,则将使用默认实现,该实现将打开数据集、获取文件列表、关闭数据集,然后尝试复制所有文件(基于共享基名)。如果默认的复制操作无法在文件之间建立关系(即公共基名或词干)以指示如何将文件组重命名为新模式,则该操作将失败。

可选地,可以传入空的hDriver参数,在这种情况下,将通过首先打开数据源来选择适当的驱动程序。

复制基本上与重命名相同,但原始文件不变。请注意,这种形式的copy与CreateCopy()不同,因为它在新位置保留磁盘上的确切二进制文件,而CreateCopy()只是尝试用与建模和通过GDAL执行的数据基本相同的数据重新生成新的数据集。

pfnDelete()

删除操作默认实现将扩展为使用GetFileList()结果。

支持功能

应提供某种支持功能,以便轻松识别与文件关联的world文件、.aux文件和.prj文件。

驱动程序已更新

预计大多数常用的驱动程序将使用自定义的GetFileList()方法进行更新,这些方法将解释世界文件和其他特殊文件。将特别强调处理gdal/frmts/raw中由头文件和原始二进制文件组成的各种格式。

未更新的“单文件格式”的驱动程序仍将使用默认逻辑,该逻辑应该工作得相当好,但可能会忽略辅助世界文件。

  • VRT:我不希望在这个时候更新VRT驱动程序,因为为某些类型的虚拟文件收集文件列表变得非常复杂。还不清楚相关文件是否应该被视为虚拟数据集的“所有者”。

  • AIGRID:我将实现一个自定义的重命名操作,试图优雅地处理这种面向目录的格式。

附加说明

  • 子数据集通常会从GetFileList()返回一个空文件列表,并且无法通过重命名或删除进行管理,尽管非常复杂的驱动程序可以实现这些操作。

  • 没有任何机制可以确保在删除文件之前将其关闭。如果应用程序无法确保此重命名/移动操作在win32上可能失败,因为它不允许对打开的文件执行重命名/删除操作。事情很容易就处于不一致的状态。

  • 文件系统中没有关联文件的数据集将返回空文件列表。这从本质上说是“无法管理的”。

实施计划

这个更改将由Frank wartemdam在trunk中为1.5.0版本及时实现。

SWIG含义

驱动程序上的GDALRenameDataset()和GDALCopyDatasetFiles()操作以及数据集上的GetFileList()操作需要通过SWIG公开。

测试

Rename和CopyFiles测试将添加到回归测试中,用于一些有代表性的格式。这些重命名操作将在一个目录和另一个目录之间进行,并且不会测试必须手动测试的跨文件系统复制。

将实现一个小型gdalmanage实用程序,允许以方便的方式使用和测试命令行中的标识、重命名、复制和删除操作。